Commit 650d2133 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull Kbuild fixes from Nicolas Schier:

 - modpost: prevent stack buffer overflow in do_input_entry() and
   do_dmi_entry()

   Defensively replace unbound sprintf() calls in file2alias to prevent
   silent stack overflows and detect alias name overflows with proper
   error message.

 - kbuild: pacman-pkg: make "rc" releases adhere to pacman versioning
   scheme

   Enable smooth upgrades from "rc" releases w/ pacman packages.

* tag 'kbuild-fixes-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux:
  kbuild: pacman-pkg: make "rc" releases adhere to pacman versioning scheme
  modpost: prevent stack buffer overflow in do_input_entry() and do_dmi_entry()
parents c6e99c10 20255071
Loading
Loading
Loading
Loading
+53 −26
Original line number Diff line number Diff line
@@ -651,7 +651,26 @@ static void do_vio_entry(struct module *mod, void *symval)
	module_alias_printf(mod, true, "%s", alias);
}

static void do_input(char *alias,
static void __attribute__((format(printf, 3, 4)))
alias_append(char *alias, size_t size, const char *fmt, ...)
{
	size_t len = strlen(alias);
	va_list args;
	int n;

	if (len >= size)
		fatal("alias buffer (%zu) overflow before append\n", size);

	va_start(args, fmt);
	n = vsnprintf(alias + len, size - len, fmt, args);
	va_end(args);

	if (n < 0 || (size_t)n >= size - len)
		fatal("alias buffer (%zu) overflow on append (need %d, have %zu)\n",
		      size, n, size - len);
}

static void do_input(char *alias, size_t size,
		     kernel_ulong_t *arr, unsigned int min, unsigned int max)
{
	unsigned int i;
@@ -659,13 +678,14 @@ static void do_input(char *alias,
	for (i = min; i <= max; i++)
		if (get_unaligned_native(arr + i / BITS_PER_LONG) &
		    (1ULL << (i % BITS_PER_LONG)))
			sprintf(alias + strlen(alias), "%X,*", i);
			alias_append(alias, size, "%X,*", i);
}

/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
static void do_input_entry(struct module *mod, void *symval)
{
	char alias[256] = {};
	const size_t sizeof_alias = sizeof(alias);

	DEF_FIELD(symval, input_device_id, flags);
	DEF_FIELD(symval, input_device_id, bustype);
@@ -687,35 +707,35 @@ static void do_input_entry(struct module *mod, void *symval)
	ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
	ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);

	sprintf(alias + strlen(alias), "-e*");
	alias_append(alias, sizeof_alias, "-e*");
	if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
		do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
	sprintf(alias + strlen(alias), "k*");
		do_input(alias, sizeof_alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
	alias_append(alias, sizeof_alias, "k*");
	if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
		do_input(alias, *keybit,
		do_input(alias, sizeof_alias, *keybit,
			 INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
			 INPUT_DEVICE_ID_KEY_MAX);
	sprintf(alias + strlen(alias), "r*");
	alias_append(alias, sizeof_alias, "r*");
	if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
		do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
	sprintf(alias + strlen(alias), "a*");
		do_input(alias, sizeof_alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
	alias_append(alias, sizeof_alias, "a*");
	if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
		do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
	sprintf(alias + strlen(alias), "m*");
		do_input(alias, sizeof_alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
	alias_append(alias, sizeof_alias, "m*");
	if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
		do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
	sprintf(alias + strlen(alias), "l*");
		do_input(alias, sizeof_alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
	alias_append(alias, sizeof_alias, "l*");
	if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
		do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
	sprintf(alias + strlen(alias), "s*");
		do_input(alias, sizeof_alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
	alias_append(alias, sizeof_alias, "s*");
	if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
		do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
	sprintf(alias + strlen(alias), "f*");
		do_input(alias, sizeof_alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
	alias_append(alias, sizeof_alias, "f*");
	if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
		do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
	sprintf(alias + strlen(alias), "w*");
		do_input(alias, sizeof_alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
	alias_append(alias, sizeof_alias, "w*");
	if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
		do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
		do_input(alias, sizeof_alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);

	module_alias_printf(mod, false, "input:%s", alias);
}
@@ -895,12 +915,16 @@ static const struct dmifield {
	{ NULL,  DMI_NONE }
};

static void dmi_ascii_filter(char *d, const char *s)
static void dmi_ascii_filter(char *d, size_t avail, const char *s)
{
	/* Filter out characters we don't want to see in the modalias string */
	for (; *s; s++)
		if (*s > ' ' && *s < 127 && *s != ':')
		if (*s > ' ' && *s < 127 && *s != ':') {
			if (avail <= 1)
				fatal("%s: alias buffer overflow\n", __func__);
			*(d++) = *s;
			avail--;
		}

	*d = 0;
}
@@ -909,6 +933,8 @@ static void dmi_ascii_filter(char *d, const char *s)
static void do_dmi_entry(struct module *mod, void *symval)
{
	char alias[256] = {};
	const size_t sizeof_alias = sizeof(alias);
	size_t len;
	int i, j;
	DEF_FIELD_ADDR(symval, dmi_system_id, matches);

@@ -916,11 +942,12 @@ static void do_dmi_entry(struct module *mod, void *symval)
		for (j = 0; j < 4; j++) {
			if ((*matches)[j].slot &&
			    (*matches)[j].slot == dmi_fields[i].field) {
				sprintf(alias + strlen(alias), ":%s*",
				alias_append(alias, sizeof_alias, ":%s*",
					     dmi_fields[i].prefix);
				dmi_ascii_filter(alias + strlen(alias),
				len = strlen(alias);
				dmi_ascii_filter(alias + len, sizeof_alias - len,
						 (*matches)[j].substr);
				strcat(alias, "*");
				alias_append(alias, sizeof_alias, "*");
			}
		}
	}
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ for pkg in $_extrapackages; do
	pkgname+=("${pkgbase}-${pkg}")
done

pkgver="${KERNELRELEASE//-/_}"
pkgver="$(echo "${KERNELRELEASE}" | sed 's/-\(rc[0-9]\+\)/\1/;s/-/_/g')"
# The PKGBUILD is evaluated multiple times.
# Running scripts/build-version from here would introduce inconsistencies.
pkgrel="${KBUILD_REVISION}"