diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-05-12 07:42:52 -0700 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2020-06-22 23:26:13 +0000 |
commit | dd9cf929e7ec79e5341a44119e00d70ec7dd5f51 (patch) | |
tree | cfd40a252329deccb35412d9b03512fd8674318d | |
parent | 0e9b286afe1224b91ff00936058b084ad4b776e4 (diff) | |
download | pam-dd9cf929e7ec79e5341a44119e00d70ec7dd5f51.tar.gz pam-dd9cf929e7ec79e5341a44119e00d70ec7dd5f51.tar.bz2 pam-dd9cf929e7ec79e5341a44119e00d70ec7dd5f51.zip |
modules/pam_limits: add support for nonewprivs
Expose prctl(PR_SET_NO_NEW_PRIVS) as "nonewprivs" item.
The valid values are a boolean toggle 0/1 to keep semi-consistent
with the other numeric limits. It's slightly awkward as this is
an oddball relative to the other items in pam_limits but outside
of the item value itself this does seem at home in pam_limits.
Resolves: https://github.com/linux-pam/linux-pam/issues/224
Resolves: https://github.com/linux-pam/linux-pam/pull/225
-rw-r--r-- | modules/pam_limits/limits.conf.5.xml | 11 | ||||
-rw-r--r-- | modules/pam_limits/pam_limits.c | 47 |
2 files changed, 47 insertions, 11 deletions
diff --git a/modules/pam_limits/limits.conf.5.xml b/modules/pam_limits/limits.conf.5.xml index 380a1399..cd64ac90 100644 --- a/modules/pam_limits/limits.conf.5.xml +++ b/modules/pam_limits/limits.conf.5.xml @@ -228,6 +228,13 @@ </listitem> </varlistentry> <varlistentry> + <term><option>nonewprivs</option></term> + <listitem> + <para>value of 0 or 1; if set to 1 disables acquiring new + privileges by invoking prctl(PR_SET_NO_NEW_PRIVS)</para> + </listitem> + </varlistentry> + <varlistentry> <term><option>priority</option></term> <listitem> <para>the priority to run user process with (negative @@ -274,7 +281,8 @@ <para> All items support the values <emphasis>-1</emphasis>, <emphasis>unlimited</emphasis> or <emphasis>infinity</emphasis> indicating no limit, - except for <emphasis remap='B'>priority</emphasis> and <emphasis remap='B'>nice</emphasis>. + except for <emphasis remap='B'>priority</emphasis>, <emphasis remap='B'>nice</emphasis>, + and <emphasis remap='B'>nonewprivs</emphasis>. </para> <para> If a hard limit or soft limit of a resource is set to a valid value, @@ -323,6 +331,7 @@ @faculty hard nproc 50 ftp hard nproc 0 @student - maxlogins 4 +@student - nonewprivs 1 :123 hard cpu 5000 @500: soft cpu 10000 600:700 hard locks 10 diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index b791cdce..9ecc272a 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -28,6 +28,7 @@ #include <syslog.h> #include <stdarg.h> #include <signal.h> +#include <sys/prctl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/resource.h> @@ -88,6 +89,7 @@ struct pam_limit_s { int flag_numsyslogins; /* whether to limit logins only for a specific user or to count all logins */ int priority; /* the priority to run user process with */ + int nonewprivs; /* whether to prctl(PR_SET_NO_NEW_PRIVS) */ struct user_limits_struct limits[RLIM_NLIMITS]; const char *conf_file; int utmp_after_pam_call; @@ -98,6 +100,7 @@ struct pam_limit_s { #define LIMIT_NUMSYSLOGINS RLIM_NLIMITS+2 #define LIMIT_PRI RLIM_NLIMITS+3 +#define LIMIT_NONEWPRIVS RLIM_NLIMITS+4 #define LIMIT_SOFT 1 #define LIMIT_HARD 2 @@ -551,6 +554,8 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, pl->flag_numsyslogins = 1; } else if (strcmp(lim_item, "priority") == 0) { limit_item = LIMIT_PRI; + } else if (strcmp(lim_item, "nonewprivs") == 0) { + limit_item = LIMIT_NONEWPRIVS; } else { pam_syslog(pamh, LOG_DEBUG, "unknown limit item '%s'", lim_item); return; @@ -562,11 +567,23 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, limit_type=LIMIT_HARD; else if (strcmp(lim_type,"-")==0) limit_type=LIMIT_SOFT | LIMIT_HARD; - else if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS) { + else if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS + && limit_item != LIMIT_NONEWPRIVS) { pam_syslog(pamh, LOG_DEBUG, "unknown limit type '%s'", lim_type); return; } - if (limit_item != LIMIT_PRI + if (limit_item == LIMIT_NONEWPRIVS) { + /* just require a bool-style 0 or 1 */ + if (strcmp(lim_value, "0") == 0) { + int_value = 0; + } else if (strcmp(lim_value, "1") == 0) { + int_value = 1; + } else { + pam_syslog(pamh, LOG_DEBUG, + "wrong limit value '%s' for limit type '%s'", + lim_value, lim_type); + } + } else if (limit_item != LIMIT_PRI #ifdef RLIMIT_NICE && limit_item != RLIMIT_NICE #endif @@ -653,7 +670,8 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, if ( (limit_item != LIMIT_LOGIN) && (limit_item != LIMIT_NUMSYSLOGINS) - && (limit_item != LIMIT_PRI) ) { + && (limit_item != LIMIT_PRI) + && (limit_item != LIMIT_NONEWPRIVS) ) { if (limit_type & LIMIT_SOFT) { if (pl->limits[limit_item].src_soft < source) { return; @@ -674,14 +692,16 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, /* recent kernels support negative priority limits (=raise priority) */ if (limit_item == LIMIT_PRI) { - pl->priority = int_value; + pl->priority = int_value; + } else if (limit_item == LIMIT_NONEWPRIVS) { + pl->nonewprivs = int_value; } else { - if (pl->login_limit_def < source) { - return; - } else { - pl->login_limit = int_value; - pl->login_limit_def = source; - } + if (pl->login_limit_def < source) { + return; + } else { + pl->login_limit = int_value; + pl->login_limit_def = source; + } } } return; @@ -995,6 +1015,13 @@ static int setup_limits(pam_handle_t *pamh, retval |= LOGIN_ERR; } + if (pl->nonewprivs) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { + pam_syslog(pamh, LOG_ERR, "Could not set prctl(PR_SET_NO_NEW_PRIVS): %m"); + retval |= LIMIT_ERR; + } + } + return retval; } |