linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Vlastimil Babka <vbabka@suse.cz>
To: Kees Cook <keescook@chromium.org>
Cc: Luis Chamberlain <mcgrof@kernel.org>,
	Iurii Zaikin <yzaikin@google.com>,
	linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	linux-mm@kvack.org, Ivan Teterevkov <ivan.teterevkov@nutanix.com>,
	Michal Hocko <mhocko@kernel.org>,
	David Rientjes <rientjes@google.com>,
	Matthew Wilcox <willy@infradead.org>,
	"Eric W . Biederman" <ebiederm@xmission.com>,
	"Guilherme G . Piccoli" <gpiccoli@canonical.com>
Subject: Re: [RFC v3 1/2] kernel/sysctl: support setting sysctl parameters from kernel command line
Date: Thu, 26 Mar 2020 23:08:40 +0100	[thread overview]
Message-ID: <8afebb97-db51-5744-dca9-840dc60cd396@suse.cz> (raw)
In-Reply-To: <202003261256.950F1E5@keescook>

On 3/26/20 9:24 PM, Kees Cook wrote:
> On Thu, Mar 26, 2020 at 07:16:05PM +0100, Vlastimil Babka wrote:
>> Since the major change, I'm sending another RFC. If this approach is ok, then
>> it probably needs just some tweaks to the various error prints, and then
>> converting the rest of existing on-off aliases (if I come up with an idea how
>> to find them all). Thanks for all the feedback so far.
> 
> Yeah, I think you can drop "RFC" from this in the next version -- you're
> well into getting this finalized IMO.

Thanks!

>>
>>  .../admin-guide/kernel-parameters.txt         |  9 ++
>>  fs/proc/proc_sysctl.c                         | 90 +++++++++++++++++++
>>  include/linux/sysctl.h                        |  4 +
>>  init/main.c                                   |  2 +
>>  4 files changed, 105 insertions(+)
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index c07815d230bc..0c7e032e7c2e 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -4793,6 +4793,15 @@
>>  
>>  	switches=	[HW,M68k]
>>  
>> +	sysctl.*=	[KNL]
>> +			Set a sysctl parameter, right before loading the init
>> +			process, as if the value was written to the respective
>> +			/proc/sys/... file. Unrecognized parameters and invalid
>> +			values are reported in the kernel log. Sysctls
>> +			registered later by a loaded module cannot be set this
>> +			way.
> 
> Maybe add: "Both '.' and '/' are recognized as separators."

OK

>> +
>> +/* Set sysctl value passed on kernel command line. */
>> +static int process_sysctl_arg(char *param, char *val,
>> +			       const char *unused, void *arg)
>> +{
>> +	char *path;
>> +	struct file_system_type *proc_fs_type;
>> +	struct file *file;
>> +	int len;
>> +	int err;
>> +	loff_t pos = 0;
>> +	ssize_t wret;
>> +
>> +	if (strncmp(param, "sysctl", sizeof("sysctl") - 1))
>> +		return 0;
>> +
>> +	param += sizeof("sysctl") - 1;
>> +
>> +	if (param[0] != '/' && param[0] != '.')
>> +		return 0;
>> +
>> +	param++;
>> +
>> +	if (!proc_mnt) {
>> +		proc_fs_type = get_fs_type("proc");
>> +		if (!proc_fs_type) {
>> +			pr_err("Failed to mount procfs to set sysctl from command line");
>> +			return 0;
>> +		}
>> +		proc_mnt = kern_mount(proc_fs_type);
>> +		put_filesystem(proc_fs_type);
>> +		if (IS_ERR(proc_mnt)) {
>> +			pr_err("Failed to mount procfs to set sysctl from command line");
>> +			proc_mnt = NULL;
>> +			return 0;
>> +		}
>> +	}
>> +
>> +	len = 4 + strlen(param) + 1;
>> +	path = kmalloc(len, GFP_KERNEL);
>> +	if (!path)
>> +		panic("%s: Failed to allocate %d bytes t\n", __func__, len);
>> +
>> +	strcpy(path, "sys/");
>> +	strcat(path, param);
>> +	strreplace(path, '.', '/');
> 
> You can do the replacement against the param directly, and also avoid
> all the open-coded string manipulations:
> 
> 	strreplace(param, '.', '/');

I didn't want to modify param for the sake of error prints, but perhaps
the replacements won't confuse system admin too much?

> 	path = kasprintf(GFP_KERNEL, "sys/%s", param);

Ah yea that's nicer.

>> +
>> +	file = file_open_root(proc_mnt->mnt_root, proc_mnt, path, O_WRONLY, 0);
>> +	if (IS_ERR(file)) {
>> +		err = PTR_ERR(file);
>> +		pr_err("Error %d opening proc file %s to set sysctl parameter '%s=%s'",
>> +			err, path, param, val);
>> +		goto out;
>> +	}
>> +	len = strlen(val);
>> +	wret = kernel_write(file, val, len, &pos);
>> +	if (wret < 0) {
>> +		err = wret;
>> +		pr_err("Error %d writing to proc file %s to set sysctl parameter '%s=%s'",
>> +			err, path, param, val);
>> +	} else if (wret != len) {
>> +		pr_err("Wrote only %ld bytes of %d  writing to proc file %s to set sysctl parameter '%s=%s'",
>> +			wret, len, path, param, val);
>> +	}
>> +
>> +	filp_close(file, NULL);
> 
> Please check the return value of filp_close() and treat that as an error
> for this function too.

Well I could print it, but not much else? The unmount will probably fail
in that case?

>> +out:
>> +	kfree(path);
>> +	return 0;
>> +}
>> +
>> +void do_sysctl_args(void)
>> +{
>> +	char *command_line;
>> +
>> +	command_line = kstrdup(saved_command_line, GFP_KERNEL);
>> +	if (!command_line)
>> +		panic("%s: Failed to allocate copy of command line\n", __func__);
>> +
>> +	parse_args("Setting sysctl args", command_line,
>> +		   NULL, 0, -1, -1, NULL, process_sysctl_arg);
>> +
>> +	if (proc_mnt)
>> +		kern_unmount(proc_mnt);
> 
> I don't recommend sharing allocation lifetimes between two functions
> (process_sysctl_arg() allocs proc_mnt, and do_sysctl_args() frees it).
> And since you have a scoped lifetime, why allocate it or have it as a
> global at all? It can be stack-allocated and passed to the handler:

So the point was that the mount is only done when an applicable sysctl
parameter is found. On majority of systems there won't be any, at least
for initial X years :)

> void do_sysctl_args(void)
> {
> 	struct file_system_type *proc_fs_type;
> 	struct vfsmount *proc_mnt;
> 	char *command_line;
> 
> 	proc_fs_type = get_fs_type("proc");
> 	if (!proc_fs_type) {
> 		pr_err("Failed to mount procfs to set sysctl from command line");
> 		return;
> 	}
> 	proc_mnt = kern_mount(proc_fs_type);
> 	put_filesystem(proc_fs_type);
> 	if (IS_ERR(proc_mnt)) {
> 		pr_err("Failed to mount procfs to set sysctl from command line");
> 		return;
> 	}
> 
> 	command_line = kstrdup(saved_command_line, GFP_KERNEL);
> 	if (!command_line)
> 		panic("%s: Failed to allocate copy of command line\n",
> 			__func__);
> 
> 	parse_args("Setting sysctl args", command_line,
> 		   NULL, 0, -1, -1, proc_mnt, process_sysctl_arg);
> 
> 	kfree(command_line);
> 	kern_unmount(proc_mnt);
> }
> 
> And then pull the mount from (the hilariously overloaded name) "arg":

But I guess the "mount on first applicable argument" approach would work
with this scheme as well:

struct vfsmount *proc_mnt = NULL;
parse_args(..., &proc_mnt, ...)

Thanks!


  reply	other threads:[~2020-03-26 22:13 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-26 18:16 [RFC v3 1/2] kernel/sysctl: support setting sysctl parameters from kernel command line Vlastimil Babka
2020-03-26 18:16 ` [RFC v3 2/2] kernel/sysctl: support handling command line aliases Vlastimil Babka
2020-03-26 20:34   ` Kees Cook
2020-03-26 21:29     ` Christian Brauner
2020-03-26 20:24 ` [RFC v3 1/2] kernel/sysctl: support setting sysctl parameters from kernel command line Kees Cook
2020-03-26 22:08   ` Vlastimil Babka [this message]
2020-03-27  3:50     ` Kees Cook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8afebb97-db51-5744-dca9-840dc60cd396@suse.cz \
    --to=vbabka@suse.cz \
    --cc=ebiederm@xmission.com \
    --cc=gpiccoli@canonical.com \
    --cc=ivan.teterevkov@nutanix.com \
    --cc=keescook@chromium.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mcgrof@kernel.org \
    --cc=mhocko@kernel.org \
    --cc=rientjes@google.com \
    --cc=willy@infradead.org \
    --cc=yzaikin@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).