diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.c | 216 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 9 | ||||
| -rw-r--r-- | kernel/auditsc.c | 40 | ||||
| -rw-r--r-- | kernel/kmod.c | 120 | ||||
| -rw-r--r-- | kernel/module.c | 47 | ||||
| -rw-r--r-- | kernel/params.c | 29 | ||||
| -rw-r--r-- | kernel/printk.c | 2 |
7 files changed, 367 insertions, 96 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index d9b690ac684..76c9a11b72d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2,7 +2,7 @@ * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. * System-call specific features have moved to auditsc.c * - * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina. * All Rights Reserved. * * This program is free software; you can redistribute it and/or modify @@ -65,7 +65,9 @@ * (Initialization happens after skb_init is called.) */ static int audit_initialized; -/* No syscall auditing will take place unless audit_enabled != 0. */ +/* 0 - no auditing + * 1 - auditing enabled + * 2 - auditing enabled and configuration is locked/unchangeable. */ int audit_enabled; /* Default state when kernel boots without any parameters. */ @@ -239,102 +241,150 @@ void audit_log_lost(const char *message) static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) { - int old = audit_rate_limit; + int res, rc = 0, old = audit_rate_limit; + + /* check if we are locked */ + if (audit_enabled == 2) + res = 0; + else + res = 1; if (sid) { char *ctx = NULL; u32 len; - int rc; - if ((rc = selinux_sid_to_string(sid, &ctx, &len))) - return rc; - else + if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_rate_limit=%d old=%d by auid=%u subj=%s", - limit, old, loginuid, ctx); - kfree(ctx); - } else - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_rate_limit=%d old=%d by auid=%u", - limit, old, loginuid); - audit_rate_limit = limit; - return 0; + "audit_rate_limit=%d old=%d by auid=%u" + " subj=%s res=%d", + limit, old, loginuid, ctx, res); + kfree(ctx); + } else + res = 0; /* Something weird, deny request */ + } + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "audit_rate_limit=%d old=%d by auid=%u res=%d", + limit, old, loginuid, res); + + /* If we are allowed, make the change */ + if (res == 1) + audit_rate_limit = limit; + /* Not allowed, update reason */ + else if (rc == 0) + rc = -EPERM; + return rc; } static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) { - int old = audit_backlog_limit; + int res, rc = 0, old = audit_backlog_limit; + + /* check if we are locked */ + if (audit_enabled == 2) + res = 0; + else + res = 1; if (sid) { char *ctx = NULL; u32 len; - int rc; - if ((rc = selinux_sid_to_string(sid, &ctx, &len))) - return rc; - else + if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_backlog_limit=%d old=%d by auid=%u subj=%s", - limit, old, loginuid, ctx); - kfree(ctx); - } else - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_backlog_limit=%d old=%d by auid=%u", - limit, old, loginuid); - audit_backlog_limit = limit; - return 0; + "audit_backlog_limit=%d old=%d by auid=%u" + " subj=%s res=%d", + limit, old, loginuid, ctx, res); + kfree(ctx); + } else + res = 0; /* Something weird, deny request */ + } + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "audit_backlog_limit=%d old=%d by auid=%u res=%d", + limit, old, loginuid, res); + + /* If we are allowed, make the change */ + if (res == 1) + audit_backlog_limit = limit; + /* Not allowed, update reason */ + else if (rc == 0) + rc = -EPERM; + return rc; } static int audit_set_enabled(int state, uid_t loginuid, u32 sid) { - int old = audit_enabled; + int res, rc = 0, old = audit_enabled; - if (state != 0 && state != 1) + if (state < 0 || state > 2) return -EINVAL; + /* check if we are locked */ + if (audit_enabled == 2) + res = 0; + else + res = 1; + if (sid) { char *ctx = NULL; u32 len; - int rc; - if ((rc = selinux_sid_to_string(sid, &ctx, &len))) - return rc; - else + if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_enabled=%d old=%d by auid=%u subj=%s", - state, old, loginuid, ctx); - kfree(ctx); - } else - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_enabled=%d old=%d by auid=%u", - state, old, loginuid); - audit_enabled = state; - return 0; + "audit_enabled=%d old=%d by auid=%u" + " subj=%s res=%d", + state, old, loginuid, ctx, res); + kfree(ctx); + } else + res = 0; /* Something weird, deny request */ + } + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "audit_enabled=%d old=%d by auid=%u res=%d", + state, old, loginuid, res); + + /* If we are allowed, make the change */ + if (res == 1) + audit_enabled = state; + /* Not allowed, update reason */ + else if (rc == 0) + rc = -EPERM; + return rc; } static int audit_set_failure(int state, uid_t loginuid, u32 sid) { - int old = audit_failure; + int res, rc = 0, old = audit_failure; if (state != AUDIT_FAIL_SILENT && state != AUDIT_FAIL_PRINTK && state != AUDIT_FAIL_PANIC) return -EINVAL; + /* check if we are locked */ + if (audit_enabled == 2) + res = 0; + else + res = 1; + if (sid) { char *ctx = NULL; u32 len; - int rc; - if ((rc = selinux_sid_to_string(sid, &ctx, &len))) - return rc; - else + if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_failure=%d old=%d by auid=%u subj=%s", - state, old, loginuid, ctx); - kfree(ctx); - } else - audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, - "audit_failure=%d old=%d by auid=%u", - state, old, loginuid); - audit_failure = state; - return 0; + "audit_failure=%d old=%d by auid=%u" + " subj=%s res=%d", + state, old, loginuid, ctx, res); + kfree(ctx); + } else + res = 0; /* Something weird, deny request */ + } + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "audit_failure=%d old=%d by auid=%u res=%d", + state, old, loginuid, res); + + /* If we are allowed, make the change */ + if (res == 1) + audit_failure = state; + /* Not allowed, update reason */ + else if (rc == 0) + rc = -EPERM; + return rc; } static int kauditd_thread(void *dummy) @@ -599,6 +649,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_DEL: if (nlmsg_len(nlh) < sizeof(struct audit_rule)) return -EINVAL; + if (audit_enabled == 2) { + ab = audit_log_start(NULL, GFP_KERNEL, + AUDIT_CONFIG_CHANGE); + if (ab) { + audit_log_format(ab, + "pid=%d uid=%u auid=%u", + pid, uid, loginuid); + if (sid) { + if (selinux_sid_to_string( + sid, &ctx, &len)) { + audit_log_format(ab, + " ssid=%u", sid); + /* Maybe call audit_panic? */ + } else + audit_log_format(ab, + " subj=%s", ctx); + kfree(ctx); + } + audit_log_format(ab, " audit_enabled=%d res=0", + audit_enabled); + audit_log_end(ab); + } + return -EPERM; + } /* fallthrough */ case AUDIT_LIST: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, @@ -609,6 +683,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_DEL_RULE: if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) return -EINVAL; + if (audit_enabled == 2) { + ab = audit_log_start(NULL, GFP_KERNEL, + AUDIT_CONFIG_CHANGE); + if (ab) { + audit_log_format(ab, + "pid=%d uid=%u auid=%u", + pid, uid, loginuid); + if (sid) { + if (selinux_sid_to_string( + sid, &ctx, &len)) { + audit_log_format(ab, + " ssid=%u", sid); + /* Maybe call audit_panic? */ + } else + audit_log_format(ab, + " subj=%s", ctx); + kfree(ctx); + } + audit_log_format(ab, " audit_enabled=%d res=0", + audit_enabled); + audit_log_end(ab); + } + return -EPERM; + } /* fallthrough */ case AUDIT_LIST_RULES: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 87865f8b4ce..3749193aed8 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -937,9 +937,10 @@ static void audit_update_watch(struct audit_parent *parent, } ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, "audit updated rules specifying path="); + audit_log_format(ab, "op=updated rules specifying path="); audit_log_untrustedstring(ab, owatch->path); audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); + audit_log_format(ab, " list=%d res=1", r->listnr); audit_log_end(ab); audit_remove_watch(owatch); @@ -969,14 +970,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent) e = container_of(r, struct audit_entry, rule); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, "audit implicitly removed rule path="); + audit_log_format(ab, "op=remove rule path="); audit_log_untrustedstring(ab, w->path); if (r->filterkey) { audit_log_format(ab, " key="); audit_log_untrustedstring(ab, r->filterkey); } else audit_log_format(ab, " key=(null)"); - audit_log_format(ab, " list=%d", r->listnr); + audit_log_format(ab, " list=%d res=1", r->listnr); audit_log_end(ab); list_del(&r->rlist); @@ -1410,7 +1411,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } - audit_log_format(ab, " %s rule key=", action); + audit_log_format(ab, " op=%s rule key=", action); if (rule->filterkey) audit_log_untrustedstring(ab, rule->filterkey); else diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 298897559ca..359955800dd 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -170,6 +170,11 @@ struct audit_aux_data_sockaddr { char a[0]; }; +struct audit_aux_data_fd_pair { + struct audit_aux_data d; + int fd[2]; +}; + struct audit_aux_data_path { struct audit_aux_data d; struct dentry *dentry; @@ -961,6 +966,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); break; } + case AUDIT_FD_PAIR: { + struct audit_aux_data_fd_pair *axs = (void *)aux; + audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]); + break; } + } audit_log_end(ab); } @@ -1815,6 +1825,36 @@ int audit_socketcall(int nargs, unsigned long *args) } /** + * __audit_fd_pair - record audit data for pipe and socketpair + * @fd1: the first file descriptor + * @fd2: the second file descriptor + * + * Returns 0 for success or NULL context or < 0 on error. + */ +int __audit_fd_pair(int fd1, int fd2) +{ + struct audit_context *context = current->audit_context; + struct audit_aux_data_fd_pair *ax; + + if (likely(!context)) { + return 0; + } + + ax = kmalloc(sizeof(*ax), GFP_KERNEL); + if (!ax) { + return -ENOMEM; + } + + ax->fd[0] = fd1; + ax->fd[1] = fd2; + + ax->d.type = AUDIT_FD_PAIR; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; +} + +/** * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto * @len: data length in user space * @a: data address in kernel space diff --git a/kernel/kmod.c b/kernel/kmod.c index 796276141e5..9f923f8ce6a 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -36,6 +36,8 @@ #include <linux/resource.h> #include <asm/uaccess.h> +extern int delete_module(const char *name, unsigned int flags); + extern int max_threads; static struct workqueue_struct *khelper_wq; @@ -46,6 +48,7 @@ static struct workqueue_struct *khelper_wq; modprobe_path is set via /proc/sys. */ char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe"; +struct module_kobject kmod_mk; /** * request_module - try to load a kernel module @@ -75,6 +78,11 @@ int request_module(const char *fmt, ...) static atomic_t kmod_concurrent = ATOMIC_INIT(0); #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ static int kmod_loop_msg; + char modalias[16 + MODULE_NAME_LEN] = "MODALIAS="; + char *uevent_envp[2] = { + modalias, + NULL + }; va_start(args, fmt); ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args); @@ -82,6 +90,12 @@ int request_module(const char *fmt, ...) if (ret >= MODULE_NAME_LEN) return -ENAMETOOLONG; + strcpy(&modalias[strlen("MODALIAS=")], module_name); + kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp); + + if (modprobe_path[0] == '\0') + goto out; + /* If modprobe needs a service that is in a module, we get a recursive * loop. Limit the number of running kmod threads to max_threads/2 or * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method @@ -108,9 +122,115 @@ int request_module(const char *fmt, ...) ret = call_usermodehelper(modprobe_path, argv, envp, 1); atomic_dec(&kmod_concurrent); +out: return ret; } EXPORT_SYMBOL(request_module); + +static ssize_t store_mod_request(struct module_attribute *mattr, + struct module *mod, + const char *buffer, size_t count) +{ + char name[MODULE_NAME_LEN]; + int ret; + + if (count < 1 || count+1 > MODULE_NAME_LEN) + return -EINVAL; + memcpy(name, buffer, count); + name[count] = '\0'; + if (name[count-1] == '\n') + name[count-1] = '\0'; + + ret = request_module(name); + if (ret < 0) + return ret; + return count; +} + +static struct module_attribute mod_request = { + .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE }, + .store = store_mod_request, +}; + +#ifdef CONFIG_MODULE_UNLOAD +static ssize_t store_mod_unload(struct module_attribute *mattr, + struct module *mod, + const char *buffer, size_t count) +{ + char name[MODULE_NAME_LEN]; + int ret; + + if (count < 1 || count+1 > MODULE_NAME_LEN) + return -EINVAL; + memcpy(name, buffer, count); + name[count] = '\0'; + if (name[count-1] == '\n') + name[count-1] = '\0'; + + ret = delete_module(name, O_NONBLOCK); + if (ret < 0) + return ret; + return count; +} + +static struct module_attribute mod_unload = { + .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE }, + .store = store_mod_unload, +}; +#endif + +static ssize_t show_mod_request_helper(struct module_attribute *mattr, + struct module *mod, + char *buffer) +{ + return sprintf(buffer, "%s\n", modprobe_path); +} + +static ssize_t store_mod_request_helper(struct module_attribute *mattr, + struct module *mod, + const char *buffer, size_t count) +{ + if (count < 1 || count+1 > KMOD_PATH_LEN) + return -EINVAL; + memcpy(modprobe_path, buffer, count); + modprobe_path[count] = '\0'; + if (modprobe_path[count-1] == '\n') + modprobe_path[count-1] = '\0'; + return count; +} + +static struct module_attribute mod_request_helper = { + .attr = { + .name = "mod_request_helper", + .mode = S_IWUSR | S_IRUGO, + .owner = THIS_MODULE + }, + .show = show_mod_request_helper, + .store = store_mod_request_helper, +}; + +void __init kmod_sysfs_init(void) +{ + int ret; + + kmod_mk.mod = THIS_MODULE; + kobj_set_kset_s(&kmod_mk, module_subsys); + kobject_set_name(&kmod_mk.kobj, "kmod"); + kobject_init(&kmod_mk.kobj); + ret = kobject_add(&kmod_mk.kobj); + if (ret < 0) + goto out; + + ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr); + ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr); +#ifdef CONFIG_MODULE_UNLOAD + ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr); +#endif + + kobject_uevent(&kmod_mk.kobj, KOBJ_ADD); +out: + return; +} #endif /* CONFIG_KMOD */ struct subprocess_info { diff --git a/kernel/module.c b/kernel/module.c index 8a94e054230..8c25b1a04fa 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -653,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod) mutex_lock(&module_mutex); } -asmlinkage long -sys_delete_module(const char __user *name_user, unsigned int flags) +int delete_module(const char *name, unsigned int flags) { struct module *mod; - char name[MODULE_NAME_LEN]; int ret, forced = 0; - if (!capable(CAP_SYS_MODULE)) - return -EPERM; - - if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) - return -EFAULT; - name[MODULE_NAME_LEN-1] = '\0'; - if (mutex_lock_interruptible(&module_mutex) != 0) return -EINTR; @@ -727,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags) return ret; } +asmlinkage long +sys_delete_module(const char __user *name_user, unsigned int flags) +{ + char name[MODULE_NAME_LEN]; + + if (!capable(CAP_SYS_MODULE)) + return -EPERM; + + if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) + return -EFAULT; + name[MODULE_NAME_LEN-1] = '\0'; + + return delete_module(name, flags); +} + static void print_unload_info(struct seq_file *m, struct module *mod) { struct module_use *use; @@ -1068,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod) } #endif /* CONFIG_KALLSYMS */ -static int module_add_modinfo_attrs(struct module *mod) +#ifdef CONFIG_SYSFS +int module_add_modinfo_attrs(struct module *mod) { struct module_attribute *attr; struct module_attribute *temp_attr; @@ -1094,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod) return error; } -static void module_remove_modinfo_attrs(struct module *mod) +void module_remove_modinfo_attrs(struct module *mod) { struct module_attribute *attr; int i; @@ -1109,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod) } kfree(mod->modinfo_attrs); } +#endif -static int mod_sysfs_init(struct module *mod) +#ifdef CONFIG_SYSFS +int mod_sysfs_init(struct module *mod) { int err; @@ -1133,7 +1142,7 @@ out: return err; } -static int mod_sysfs_setup(struct module *mod, +int mod_sysfs_setup(struct module *mod, struct kernel_param *kparam, unsigned int num_params) { @@ -1169,16 +1178,14 @@ out_unreg: out: return err; } +#endif static void mod_kobject_remove(struct module *mod) { module_remove_modinfo_attrs(mod); module_param_sysfs_remove(mod); - if (mod->mkobj.drivers_dir) - kobject_unregister(mod->mkobj.drivers_dir); - if (mod->holders_dir) - kobject_unregister(mod->holders_dir); - + kobject_unregister(mod->mkobj.drivers_dir); + kobject_unregister(mod->holders_dir); kobject_unregister(&mod->mkobj.kobj); } @@ -2345,6 +2352,7 @@ void print_modules(void) printk("\n"); } +#ifdef CONFIG_SYSFS static char *make_driver_name(struct device_driver *drv) { char *driver_name; @@ -2419,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv) } } EXPORT_SYMBOL(module_remove_driver); +#endif #ifdef CONFIG_MODVERSIONS /* Generate the signature for struct module here, too, for modversions. */ diff --git a/kernel/params.c b/kernel/params.c index 553cf7d6a4b..7a751570b56 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -30,8 +30,6 @@ #define DEBUGP(fmt, a...) #endif -static struct kobj_type module_ktype; - static inline char dash2underscore(char c) { if (c == '-') @@ -391,6 +389,7 @@ struct module_param_attrs struct param_attribute attrs[0]; }; +#ifdef CONFIG_SYSFS #define to_param_attr(n) container_of(n, struct param_attribute, mattr); static ssize_t param_attr_show(struct module_attribute *mattr, @@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, return len; return err; } +#endif #ifdef CONFIG_MODULES #define __modinit @@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr, #define __modinit __init #endif +#ifdef CONFIG_SYSFS /* * param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME * @mk: struct module_kobject (contains parent kobject) @@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk, return mp; } - #ifdef CONFIG_MODULES - /* * module_param_sysfs_setup - setup sysfs support for one module * @mod: module @@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void) /* module-related sysfs stuff */ -#ifdef CONFIG_SYSFS #define to_module_attr(n) container_of(n, struct module_attribute, attr); #define to_module_kobject(n) container_of(n, struct module_kobject, kobj); @@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = { .store = module_attr_store, }; +static struct kobj_type module_ktype; + static int uevent_filter(struct kset *kset, struct kobject *kobj) { struct kobj_type *ktype = get_ktype(kobj); @@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = { .filter = uevent_filter, }; -#else -static struct sysfs_ops module_sysfs_ops = { - .show = NULL, - .store = NULL, -}; -#endif +decl_subsys(module, &module_ktype, &module_uevent_ops); static struct kobj_type module_ktype = { .sysfs_ops = &module_sysfs_ops, }; -decl_subsys(module, &module_ktype, &module_uevent_ops); - /* * param_sysfs_init - wrapper for built-in params support */ @@ -714,11 +707,21 @@ static int __init param_sysfs_init(void) } param_sysfs_builtin(); + kmod_sysfs_init(); return 0; } subsys_initcall(param_sysfs_init); +#else +#if 0 +static struct sysfs_ops module_sysfs_ops = { + .show = NULL, + .store = NULL, +}; +#endif +#endif + EXPORT_SYMBOL(param_set_byte); EXPORT_SYMBOL(param_get_byte); EXPORT_SYMBOL(param_set_short); diff --git a/kernel/printk.c b/kernel/printk.c index 0c151877ff7..4b47e59248d 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -54,7 +54,7 @@ int console_printk[4] = { }; /* - * Low lever drivers may need that to know if they can schedule in + * Low level drivers may need that to know if they can schedule in * their unblank() callback or not. So let's export it. */ int oops_in_progress; |