summaryrefslogtreecommitdiff
path: root/modules/pam_limits
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2020-05-12 07:42:52 -0700
committerDmitry V. Levin <ldv@altlinux.org>2020-06-22 23:26:13 +0000
commitdd9cf929e7ec79e5341a44119e00d70ec7dd5f51 (patch)
treecfd40a252329deccb35412d9b03512fd8674318d /modules/pam_limits
parent0e9b286afe1224b91ff00936058b084ad4b776e4 (diff)
downloadlinux-pam-git-dd9cf929e7ec79e5341a44119e00d70ec7dd5f51.tar.gz
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
Diffstat (limited to 'modules/pam_limits')
-rw-r--r--modules/pam_limits/limits.conf.5.xml11
-rw-r--r--modules/pam_limits/pam_limits.c47
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;
}