summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2011-02-04 12:46:38 +0100
committerLennart Poettering <lennart@poettering.net>2011-02-04 12:46:38 +0100
commitb20c6be697ded108e3c3bd5b8812fee13326eefc (patch)
tree2c8be1fc5eb7c60e1c1ece7e93368bb903229731
parent7115593375de5c84d44df9aafb011da4a1385569 (diff)
pam: optionally reset cgroup memberships for login sessions
-rw-r--r--man/pam_systemd.xml38
-rw-r--r--src/load-fragment.c1
-rw-r--r--src/pam-module.c60
3 files changed, 72 insertions, 27 deletions
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index eddd8e003f..6fe6981011 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -222,17 +222,30 @@
separated list of cgroup controllers
in which hierarchies a user/session
cgroup will be created by default for
- each user logging in. If ommited,
- defaults to 'cpu', meaning that in
- addition to creating per-user and
- per-session cgroups in systemd's own
- hierarchy, groups are created in the
- 'cpu' hierarchy, on order to ensure
- that every use and every sessions gets
- an equal amount of CPU time,
- regardless how many processes a user
- or session might
- own.</para></listitem>
+ each user logging in, in addition to
+ the cgroup in the named 'name=systemd'
+ hierarchy. If ommited, defaults to an
+ empty list. This may be used to move
+ user sessions into their own groups in
+ the 'cpu' hierarchy which ensures that
+ every logged in user gets an equal
+ amount of CPU time regardless how many
+ processes he has
+ started.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>reset-controllers=</option></term>
+
+ <listitem><para>Takes a comma
+ separated list of cgroup controllers
+ in which hierarchies the logged in
+ processes will be reset to the root
+ cgroup. If ommited, defaults to 'cpu',
+ meaning that a 'cpu' cgroup grouping
+ inherited from the login manager will
+ be reset for the processes of the
+ logged in user.</para></listitem>
</varlistentry>
</variablelist>
@@ -245,7 +258,8 @@
<option>create-session=1</option>,
<option>kill-session=0</option>,
<option>kill-user=0</option>,
- <option>keep-root=1</option>.</para>
+ <option>keep-root=1</option>,
+ <option>reset-controllers=cpu</option>.</para>
</refsect1>
<refsect1>
diff --git a/src/load-fragment.c b/src/load-fragment.c
index fc64ddd5a0..ab2bcd2d2f 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -918,7 +918,6 @@ static int config_parse_limit(
struct rlimit **rl = data;
unsigned long long u;
- int r;
assert(filename);
assert(lvalue);
diff --git a/src/pam-module.c b/src/pam-module.c
index fc3aac185d..117df05181 100644
--- a/src/pam-module.c
+++ b/src/pam-module.c
@@ -43,12 +43,11 @@ static int parse_argv(pam_handle_t *handle,
bool *kill_session,
bool *kill_user,
bool *keep_root,
- char ***controllers) {
+ char ***controllers,
+ char ***reset_controllers) {
unsigned i;
-#if 0
- bool controller_set = false;
-#endif
+ bool reset_controller_set = false;
assert(argc >= 0);
assert(argc == 0 || argv);
@@ -106,9 +105,21 @@ static int parse_argv(pam_handle_t *handle,
*controllers = l;
}
-#if 0
- controller_set = true;
-#endif
+ } else if (startswith(argv[i], "reset-controllers=")) {
+
+ if (reset_controllers) {
+ char **l;
+
+ if (!(l = strv_split(argv[i] + 18, ","))) {
+ pam_syslog(handle, LOG_ERR, "Out of memory.");
+ return -ENOMEM;
+ }
+
+ strv_free(*reset_controllers);
+ *reset_controllers = l;
+ }
+
+ reset_controller_set = true;
} else {
pam_syslog(handle, LOG_ERR, "Unknown parameter '%s'.", argv[i]);
@@ -116,8 +127,7 @@ static int parse_argv(pam_handle_t *handle,
}
}
-#if 0
- if (!controller_set && controllers) {
+ if (!reset_controller_set && reset_controllers) {
char **l;
if (!(l = strv_new("cpu", NULL))) {
@@ -125,13 +135,15 @@ static int parse_argv(pam_handle_t *handle,
return -ENOMEM;
}
- *controllers = l;
+ *reset_controllers = l;
}
-#endif
if (controllers)
strv_remove(*controllers, "name=systemd");
+ if (reset_controllers)
+ strv_remove(*reset_controllers, "name=systemd");
+
if (kill_session && *kill_session && kill_user)
*kill_user = true;
@@ -320,6 +332,22 @@ static int create_user_group(
return PAM_SUCCESS;
}
+static int reset_group(
+ pam_handle_t *handle,
+ const char *controller) {
+
+ int r;
+
+ assert(handle);
+
+ if ((r = cg_attach(controller, "/", 0)) < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to reset cgroup for controller %s: %s", controller, strerror(-r));
+ return PAM_SESSION_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
_public_ PAM_EXTERN int pam_sm_open_session(
pam_handle_t *handle,
int flags,
@@ -331,7 +359,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
char *buf = NULL;
int lock_fd = -1;
bool create_session = true;
- char **controllers = NULL, **c;
+ char **controllers = NULL, **reset_controllers = NULL, **c;
assert(handle);
@@ -341,7 +369,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (sd_booted() <= 0)
return PAM_SUCCESS;
- if (parse_argv(handle, argc, argv, &create_session, NULL, NULL, NULL, &controllers) < 0)
+ if (parse_argv(handle, argc, argv, &create_session, NULL, NULL, NULL, &controllers, &reset_controllers) < 0)
return PAM_SESSION_ERR;
if ((r = get_user_data(handle, &username, &pw)) != PAM_SUCCESS)
@@ -429,6 +457,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
STRV_FOREACH(c, controllers)
create_user_group(handle, *c, buf, pw, true, false);
+ STRV_FOREACH(c, reset_controllers)
+ reset_group(handle, *c);
+
r = PAM_SUCCESS;
finish:
@@ -438,6 +469,7 @@ finish:
close_nointr_nofail(lock_fd);
strv_free(controllers);
+ strv_free(reset_controllers);
return r;
}
@@ -490,7 +522,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if (sd_booted() <= 0)
return PAM_SUCCESS;
- if (parse_argv(handle, argc, argv, NULL, &kill_session, &kill_user, &keep_root, &controllers) < 0)
+ if (parse_argv(handle, argc, argv, NULL, &kill_session, &kill_user, &keep_root, &controllers, NULL) < 0)
return PAM_SESSION_ERR;
if ((r = get_user_data(handle, &username, &pw)) != PAM_SUCCESS)