diff options
author | Karel Zak | 2011-11-16 13:21:40 +0100 |
---|---|---|
committer | Karel Zak | 2011-11-16 13:21:40 +0100 |
commit | 94c0166257748110181f1a18d5851d931c2d1a12 (patch) | |
tree | d585ce3f703c82068ada8d17cb713dc98a93d226 /sys-utils/prlimit.c | |
parent | prlimit: fix typo in man page, option --verbose (diff) | |
download | kernel-qcow2-util-linux-94c0166257748110181f1a18d5851d931c2d1a12.tar.gz kernel-qcow2-util-linux-94c0166257748110181f1a18d5851d931c2d1a12.tar.xz kernel-qcow2-util-linux-94c0166257748110181f1a18d5851d931c2d1a12.zip |
prlimit: avoid segfault due to array-out-of-bounds error
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
Reported-by: Bernhard Voelker <mail@bernhard-voelker.de>
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/prlimit.c')
-rw-r--r-- | sys-utils/prlimit.c | 102 |
1 files changed, 63 insertions, 39 deletions
diff --git a/sys-utils/prlimit.c b/sys-utils/prlimit.c index ead8bd40e..a99cc1e31 100644 --- a/sys-utils/prlimit.c +++ b/sys-utils/prlimit.c @@ -32,6 +32,7 @@ #include "tt.h" #include "xalloc.h" #include "strutils.h" +#include "list.h" #ifndef RLIMIT_RTTIME # define RLIMIT_RTTIME 15 @@ -84,6 +85,8 @@ static struct prlimit_desc prlimit_desc[] = }; struct prlimit { + struct list_head lims; + struct rlimit rlim; struct prlimit_desc *desc; int modify; /* PRLIMIT_{SOFT,HARD} mask */ @@ -140,6 +143,8 @@ static int prlimit(pid_t p, int resource, } #endif +static void rem_prlim(struct prlimit *lim); + static void __attribute__ ((__noreturn__)) usage(FILE * out) { size_t i; @@ -264,9 +269,10 @@ 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 list_head *lims, int tt_flags) { int i; + struct list_head *p, *pnext; struct tt *tt; tt = tt_new_table(tt_flags); @@ -284,9 +290,13 @@ static int show_limits(struct prlimit lims[], size_t n, int tt_flags) } } - for (i = 0; (size_t) i < n; i++) - if (!lims[i].modify) /* only display old limits */ - add_tt_line(tt, &lims[i]); + + list_for_each_safe(p, pnext, lims) { + struct prlimit *lim = list_entry(p, struct prlimit, lims); + + add_tt_line(tt, lim); + rem_prlim(lim); + } tt_print_table(tt); done: @@ -313,13 +323,13 @@ static void get_unknown_hardsoft(struct prlimit *lim) lim->rlim.rlim_max = old.rlim_max; } -static void do_prlimit(struct prlimit lims[], size_t n, int tt_flags) +static void do_prlimit(struct list_head *lims) { - size_t i, nshows = 0; + struct list_head *p, *pnext; - for (i = 0; i < n; i++) { + list_for_each_safe(p, pnext, lims) { struct rlimit *new = NULL; - struct prlimit *lim = &lims[i]; + struct prlimit *lim = list_entry(p, struct prlimit, lims); if (lim->modify) { if (lim->modify != (PRLIMIT_HARD | PRLIMIT_SOFT)) @@ -331,8 +341,7 @@ static void do_prlimit(struct prlimit lims[], size_t n, int tt_flags) errx(EXIT_FAILURE, _("the soft limit %s cannot exceed the hard limit"), lim->desc->name); new = &lim->rlim; - } else - nshows++; + } if (verbose && new) { printf(_("New %s limit: "), lim->desc->name); @@ -352,10 +361,10 @@ static void do_prlimit(struct prlimit lims[], size_t n, int tt_flags) _("failed to set the %s resource limit") : _("failed to get the %s resource limit"), lim->desc->name); - } - if (nshows) - show_limits(lims, n, tt_flags); + if (lim->modify) + rem_prlim(lim); /* modify only; don't show */ + } } @@ -438,24 +447,32 @@ static int parse_prlim(struct rlimit *lim, char *ops, size_t id) return found; } -/* - * Add a resource limit to the limits array - */ -static int add_prlim(char *ops, struct prlimit *lim, size_t id) +static struct prlimit *add_prlim(char *ops, struct list_head *lims, size_t id) { + struct prlimit *lim = calloc(1, sizeof(*lim)); + + INIT_LIST_HEAD(&lim->lims); lim->desc = &prlimit_desc[id]; if (ops) lim->modify = parse_prlim(&lim->rlim, ops, id); + list_add_tail(&lim->lims, lims); return 0; } +static void rem_prlim(struct prlimit *lim) +{ + if (!lim) + return; + list_del(&lim->lims); + free(lim); +} + int main(int argc, char **argv) { int opt, tt_flags = 0; - size_t n = 0; - struct prlimit lims[MAX_RESOURCES] = { PRLIMIT_EMPTY_LIMIT }; + struct list_head lims; enum { VERBOSE_OPTION = CHAR_MAX + 1, @@ -494,6 +511,8 @@ int main(int argc, char **argv) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + INIT_LIST_HEAD(&lims); + /* * Something is very wrong if this doesn't succeed, * assuming STACK is the last resource, of course. @@ -505,52 +524,52 @@ int main(int argc, char **argv) longopts, NULL)) != -1) { switch(opt) { case 'c': - add_prlim(optarg, &lims[n++], CORE); + add_prlim(optarg, &lims, CORE); break; case 'd': - add_prlim(optarg, &lims[n++], DATA); + add_prlim(optarg, &lims, DATA); break; case 'e': - add_prlim(optarg, &lims[n++], NICE); + add_prlim(optarg, &lims, NICE); break; case 'f': - add_prlim(optarg, &lims[n++], FSIZE); + add_prlim(optarg, &lims, FSIZE); break; case 'i': - add_prlim(optarg, &lims[n++], SIGPENDING); + add_prlim(optarg, &lims, SIGPENDING); break; case 'l': - add_prlim(optarg, &lims[n++], MEMLOCK); + add_prlim(optarg, &lims, MEMLOCK); break; case 'm': - add_prlim(optarg, &lims[n++], RSS); + add_prlim(optarg, &lims, RSS); break; case 'n': - add_prlim(optarg, &lims[n++], NOFILE); + add_prlim(optarg, &lims, NOFILE); break; case 'q': - add_prlim(optarg, &lims[n++], MSGQUEUE); + add_prlim(optarg, &lims, MSGQUEUE); break; case 'r': - add_prlim(optarg, &lims[n++], RTPRIO); + add_prlim(optarg, &lims, RTPRIO); break; case 's': - add_prlim(optarg, &lims[n++], STACK); + add_prlim(optarg, &lims, STACK); break; case 't': - add_prlim(optarg, &lims[n++], CPU); + add_prlim(optarg, &lims, CPU); break; case 'u': - add_prlim(optarg, &lims[n++], NPROC); + add_prlim(optarg, &lims, NPROC); break; case 'v': - add_prlim(optarg, &lims[n++], AS); + add_prlim(optarg, &lims, AS); break; case 'x': - add_prlim(optarg, &lims[n++], LOCKS); + add_prlim(optarg, &lims, LOCKS); break; case 'y': - add_prlim(optarg, &lims[n++], RTTIME); + add_prlim(optarg, &lims, RTTIME); break; case 'p': @@ -600,13 +619,18 @@ int main(int argc, char **argv) columns[ncolumns++] = COL_UNITS; } - if (!n) { + if (list_empty(&lims)) { /* default is to print all resources */ - for (; n < MAX_RESOURCES; n++) - add_prlim(NULL, &lims[n], n); + size_t n; + + for (n = 0; n < MAX_RESOURCES; n++) + add_prlim(NULL, &lims, n); } - do_prlimit(lims, n, tt_flags); + do_prlimit(&lims); + + if (!list_empty(&lims)) + show_limits(&lims, tt_flags); return EXIT_SUCCESS; } |