All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wen Yang <wenyang@linux.alibaba.com>
To: Alexey Gladkov <gladkov.alexey@gmail.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>,
	Lucas De Marchi <lucas.de.marchi@gmail.com>,
	Topi Miettinen <toiwoton@gmail.com>,
	linux-modules@vger.kernel.org
Subject: Re: [PATCH] libkmod: introduce kmod_module_uniq_options() to improve the reliability of loading module
Date: Wed, 6 May 2020 11:26:14 +0800	[thread overview]
Message-ID: <de672355-c3d9-9322-5a72-afeb9236e000@linux.alibaba.com> (raw)
In-Reply-To: <20200429164442.vx63qh2ioswxa4mf@comp-core-i7-2640m-0182e6>


Dear Alexey,

Thank you for your comments,
we will fix them and send a V2 soon.

Best wishes,
Wen

在 2020/4/30 上午12:44, Alexey Gladkov 写道:
> On Wed, Apr 29, 2020 at 11:52:08PM +0800, Wen Yang wrote:
>> As in commit 2045cdfa1b40 ("netfilter: nf_conntrack: Fix possible possible crash on module loading"),
>> Loading the nf_conntrack module with doubled hashsize parameter, i.e.
>> 	  modprobe nf_conntrack hashsize=12345 hashsize=12345
>> causes NULL-ptr deref.
>>
>> If 'hashsize' specified twice, the nf_conntrack_set_hashsize() function
>> will be called also twice.
>>
>> In addition, we may also construct the doubled hashsize parameter scenario by using the following configuration:
>>
>> $ cat /etc/modprobe.d/firewalld-sysctls.conf
>> install nf_conntrack /usr/sbin/modprobe --ignore-install nf_conntrack $CMDLINE_OPTS && /usr/sbin/sysctl --quiet --pattern 'net[.]netfilter[.]nf_conntrack.*' --system
>>
>> $ cat /etc/modprobe.d/nf_conntrack.conf
>> options nf_conntrack hashsize=187600
>>
>> $ sudo modprobe nf_conntrack -v
>> install /usr/sbin/modprobe --ignore-install nf_conntrack $CMDLINE_OPTS && /usr/sbin/sysctl --quiet --pattern 'net[.]netfilter[.]nf_conntrack.*' --system hashsize=187500
>> insmod /path/to/nf_conntrack.ko hashsize=187500 hashsize=187500
>>
>> Passing multiple repeated parameters to the kernel may trigger kernel bugs
>> and affect the performance of loading kernel modules.
>>
>> We introduce the nf_conntrack_set_hashsize() and hope to solve this problem.
>>
>> Signed-off-by: Wen Yang <wenyang@linux.alibaba.com>
>> Cc: Lucas De Marchi <lucas.demarchi@intel.com>
>> Cc: Lucas De Marchi <lucas.de.marchi@gmail.com>
>> Cc: Topi Miettinen <toiwoton@gmail.com>
>> Cc: Alexey Gladkov <gladkov.alexey@gmail.com>
>> Cc: linux-modules@vger.kernel.org
>> ---
>>   libkmod/libkmod-module.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
>>   libkmod/libkmod.h        |  1 +
>>   tools/insmod.c           |  7 +++++
>>   3 files changed, 80 insertions(+)
>>
>> diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
>> index 76a6dc3..f42beb8 100644
>> --- a/libkmod/libkmod-module.c
>> +++ b/libkmod/libkmod-module.c
>> @@ -1076,6 +1076,72 @@ static char *module_options_concat(const char *opt, const char *xopt)
>>   	return r;
>>   }
>>   
>> +static unsigned int module_options_cnt(const char *opts)
>> +{
>> +	int nr_opts = 0;
>> +	char *saveptr, *tok, *buf;
>> +
>> +	if (!opts)
>> +		return 0;
>> +
>> +	buf = strdup(opts);
>> +	for (tok = strtok_r(buf, " ", &saveptr); tok != NULL;
> 
> Why not use strchr() to find the " " and count them ?
> 
>> +	     tok = strtok_r(NULL, " ", &saveptr), nr_opts++) {}
>> +
> 
> Parameters can have spaces [1]. Is not it so ?
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/cmdline.c#n196
> 
>> +	free(buf);
>> +	return nr_opts;
>> +}
>> +
>> +KMOD_EXPORT int kmod_module_uniq_options(char **opts)
>> +{
>> +	char *buf;
>> +	char **array;
>> +	bool duplicated;
>> +	char *saveptr, *tok;
>> +	int nr_opts, len, i, j;
>> +
>> +	if (!opts || !*opts)
>> +		return 0;
>> +
>> +	buf = strdup(*opts);
> 
> We have the options passed as an argument. You doubled it here and tripled
> in the module_options_cnt(). Can you reduce memory usage ?
> 
>> +	if (!buf)
>> +		return  -ENOMEM;
>> +
>> +	len = strlen(buf);
>> +	nr_opts = module_options_cnt(buf);
>> +	array = calloc(nr_opts, sizeof(char *));
>> +	if (!buf)
>> +		return  -ENOMEM;
>> +
>> +	for (tok = strtok_r(buf, " ", &saveptr), i = 0; tok != NULL;
>> +			tok = strtok_r(NULL, " ", &saveptr), i++) {
>> +		array[i] = tok;
>> +	}
>> +
>> +	(*opts)[0] = '\0';
>> +	len = 0;
>> +	for (i = 0; i < nr_opts; i++) {
>> +		duplicated = false;
>> +		for (j = 0; j < i; j++) {
>> +			if (strcmp(array[i], array[j]) == 0) {
>> +				duplicated = true;
>> +				break;
>> +			}
>> +		}
>> +
>> +		if (!duplicated) {
>> +			strcat(*opts, array[i]);
>> +			strcat(*opts, " ");
>> +			len += strlen(array[i]) + 1;
>> +		}
>> +	}
>> +
>> +	(*opts)[len] = '\0';
>> +	free(buf);
>> +	free(array);
>> +	return 0;
>> +}
>> +
>>   static int __kmod_module_get_probe_list(struct kmod_module *mod,
>>   						bool required,
>>   						bool ignorecmd,
>> @@ -1322,6 +1388,12 @@ KMOD_EXPORT int kmod_module_probe_insert_module(struct kmod_module *mod,
>>   		options = module_options_concat(moptions,
>>   					m == mod ? extra_options : NULL);
>>   
>> +		err = kmod_module_uniq_options(&options);
>> +		if (err < 0) {
>> +			free(options);
>> +			return err;
>> +		}
>> +
>>   		if (cmd != NULL && !m->ignorecmd) {
>>   			if (print_action != NULL)
>>   				print_action(m, true, options ?: "");
>> diff --git a/libkmod/libkmod.h b/libkmod/libkmod.h
>> index 3cab2e5..774e52a 100644
>> --- a/libkmod/libkmod.h
>> +++ b/libkmod/libkmod.h
>> @@ -186,6 +186,7 @@ int kmod_module_probe_insert_module(struct kmod_module *mod,
>>   const char *kmod_module_get_name(const struct kmod_module *mod);
>>   const char *kmod_module_get_path(const struct kmod_module *mod);
>>   const char *kmod_module_get_options(const struct kmod_module *mod);
>> +int kmod_module_uniq_options(char **opts);
>>   const char *kmod_module_get_install_commands(const struct kmod_module *mod);
>>   const char *kmod_module_get_remove_commands(const struct kmod_module *mod);
>>   struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod);
>> diff --git a/tools/insmod.c b/tools/insmod.c
>> index c422971..2dc0c22 100644
>> --- a/tools/insmod.c
>> +++ b/tools/insmod.c
>> @@ -132,6 +132,13 @@ static int do_insmod(int argc, char *argv[])
>>   		opts[optslen] = '\0';
>>   	}
>>   
>> +	err = kmod_module_uniq_options(&opts);
>> +	if (err < 0) {
>> +		ERR("kmod_module_uniq_options() failed!\n");
>> +		free(opts);
>> +		return err;
>> +	}
>> +
>>   	ctx = kmod_new(NULL, &null_config);
>>   	if (!ctx) {
>>   		ERR("kmod_new() failed!\n");
>> -- 
>> 1.8.3.1
>>
> 

      reply	other threads:[~2020-05-06  3:26 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-29 15:52 [PATCH] libkmod: introduce kmod_module_uniq_options() to improve the reliability of loading module Wen Yang
2020-04-29 16:44 ` Alexey Gladkov
2020-05-06  3:26   ` Wen Yang [this message]

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=de672355-c3d9-9322-5a72-afeb9236e000@linux.alibaba.com \
    --to=wenyang@linux.alibaba.com \
    --cc=gladkov.alexey@gmail.com \
    --cc=linux-modules@vger.kernel.org \
    --cc=lucas.de.marchi@gmail.com \
    --cc=lucas.demarchi@intel.com \
    --cc=toiwoton@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.