[PATCH 11/15] prlimit: avoid segfault due to array-out-of-bounds error

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[PATCH 11/15] prlimit: avoid segfault due to array-out-of-bounds error

prlimit used 1 element of the lims array per limit given on the command
line argument, not being aware that a user would pass the value of the
soft and the hard limit in different options - leading to a segfault
when the user passes more than MAX_RESOURCES limit options.
As a side effect, a limit was retrieved and printed several times if
the corresponding option appeared multiple times.

Example:
$ prlimit -l -l -l -l -l -l -l -l -l -l -l -l -l -l -l -l -l -l -l
RESOURCE DESCRIPTION                         SOFT   HARD UNITS
MEMLOCK  max locked-in-memory address space 65536 262144 bytes
MEMLOCK  max locked-in-memory address space 65536 262144 bytes
...
Segmentation fault

Use the lims array in a more direct way, i.e. the index is limit id.
Initialize lims array and adapt option parsing in main() accordingly.
do_prlimits() and show_limits(): loop over all MAX_RESOURCES in the
lims array.
Fix limit parsing in parse_prlim() and add_prlim() to be aware of
soft and hard limits in separate program arguments.

Signed-off-by: Bernhard Voelker <mail@xxxxxxxxxxxxxxxxxxx>
---
 sys-utils/prlimit.c |   32 ++++++++++++++++++++++----------
 1 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/sys-utils/prlimit.c b/sys-utils/prlimit.c
index fc11a94..1d6dd92 100644
--- a/sys-utils/prlimit.c
+++ b/sys-utils/prlimit.c
@@ -265,7 +265,7 @@ static int column_name_to_id(const char *name, size_t namesz)
 	return -1;
 }

-static int show_limits(struct prlimit lims[], size_t n, int tt_flags)
+static int show_limits(struct prlimit lims[], int tt_flags)
 {
 	int i;
 	struct tt *tt;
@@ -285,7 +285,7 @@ static int show_limits(struct prlimit lims[], size_t n, int tt_flags)
 		}
 	}

-	for (i = 0; (size_t) i < n; i++)
+	for (i = 0; (size_t) i < MAX_RESOURCES; i++)
 		if (lims[i].show)
 			add_tt_line(tt, &lims[i]);

@@ -327,11 +327,11 @@ static void get_unknown_hardsoft(struct prlimit *lim)
 	}
 }

-static void do_prlimit(struct prlimit lims[], size_t n, int tt_flags)
+static void do_prlimit(struct prlimit lims[], int tt_flags)
 {
 	size_t i;

-	for (i = 0; i < n; i++) {
+	for (i = 0; i < MAX_RESOURCES; i++) {
 		struct rlimit *new = NULL;

 		if (lims[i].modify) {
@@ -458,8 +458,10 @@ static int parse_prlim(struct rlimit *lim, char *ops, size_t id)
 		errx(EXIT_FAILURE, _("failed to parse %s limit"),
 		     prlimit_desc[id].name);

-	lim->rlim_cur = soft;
-	lim->rlim_max = hard;
+	if (modify & PRLIMIT_SOFT)
+		lim->rlim_cur = soft;
+	if (modify & PRLIMIT_HARD)
+		lim->rlim_max = hard;

 	return modify;
 }
@@ -474,7 +476,7 @@ static int add_prlim(char *ops, struct prlimit *lim, size_t id)
 	if (ops) { /* planning on modifying a limit? */
 		int modify = parse_prlim(&lim->rlim, ops, id);
 		if (modify)
-			lim->modify = 1;
+			lim->modify |= modify;
 		else
 			lim->show = 1;
 	} else {
@@ -553,6 +555,15 @@ int main(int argc, char **argv)
 	 */
 	assert(MAX_RESOURCES == STACK + 1);

+	/*
+	 * initialize limits array */
+	for (n = 0; n < MAX_RESOURCES; n++) {
+		lims[n].desc = &prlimit_desc[n];
+		lims[n].rlim.rlim_cur = lims[n].rlim.rlim_max = 0;
+		lims[n].modify = lims[n].show = 0;
+	}
+	n = 0;
+
 	while((opt = getopt_long(argc, argv,
 				 "c::d::e::f::i::l::m::n::q::r::s::t::u::v::x::y::p:o:vVh",
 				 longopts, NULL)) != -1) {
@@ -573,7 +584,8 @@ int main(int argc, char **argv)
 		case 'v':
 		case 'x':
 		case 'y':
-				add_prlim(optarg, &lims[n++], opt_id[opt]);
+				add_prlim(optarg, &lims[opt_id[opt]], opt_id[opt]);
+				n++;
 				break;

 		case 'p':
@@ -629,8 +641,8 @@ int main(int argc, char **argv)
 			add_prlim(NULL, &lims[n], n);
 	}

-	do_prlimit(lims, n, tt_flags);
-	show_limits(lims, n, tt_flags);
+	do_prlimit(lims, tt_flags);
+	show_limits(lims, tt_flags);

 	return EXIT_SUCCESS;
 }
--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux