Allow to change a /proc/cmdline by a root user (writable /proc/cmdline) diff -urN linux-2.6.32-fan32d-r10303.x86_64.old/fs/proc/cmdline.c linux-2.6.32-fan32d-r10303.x86_64/fs/proc/cmdline.c --- linux-2.6.32-fan32d-r10303.x86_64.old/fs/proc/cmdline.c 2014-12-29 23:30:31.000000000 +0300 +++ linux-2.6.32-fan32d-r10303.x86_64/fs/proc/cmdline.c 2014-12-30 15:26:23.000000000 +0300 @@ -3,6 +3,7 @@ #include #include #include +#include static int cmdline_proc_show(struct seq_file *m, void *v) { @@ -24,16 +25,54 @@ return single_open(file, cmdline_proc_show, NULL); } +static ssize_t cmdline_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct ve_struct *ve = get_exec_env(); + char *cmdline; + + if (count > PAGE_SIZE - 1) + count = PAGE_SIZE - 1; + + cmdline = kzalloc(count + 1, GFP_KERNEL); + if (unlikely(!cmdline)) + return -ENOMEM; + + if (copy_from_user(cmdline, buf, count)) { + kfree(cmdline); + return -EFAULT; + } + + if (!ve_is_super(ve)) { + if (ve->proc_cmdline) { + kfree(ve->proc_cmdline); + ve->proc_cmdline = 0; + } + ve->proc_cmdline = cmdline; + } + else { + static was_here = 0; + if (was_here) + kfree(saved_command_line); + + was_here = 1; + saved_command_line = cmdline; + } + + return count; +} + static const struct file_operations cmdline_proc_fops = { .open = cmdline_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, + .write = cmdline_proc_write, }; static int __init proc_cmdline_init(void) { - proc_create("cmdline", 0, &glob_proc_root, &cmdline_proc_fops); + proc_create("cmdline", S_IRUGO|S_IWUSR, &glob_proc_root, &cmdline_proc_fops); return 0; } module_init(proc_cmdline_init);