chiark / gitweb /
pam: optionally reset cgroup memberships for login sessions
authorLennart Poettering <lennart@poettering.net>
Fri, 4 Feb 2011 11:46:38 +0000 (12:46 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 4 Feb 2011 11:46:38 +0000 (12:46 +0100)
man/pam_systemd.xml
src/load-fragment.c
src/pam-module.c

index eddd8e0..6fe6981 100644 (file)
                                 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>
 
                 <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>
index fc64ddd..ab2bcd2 100644 (file)
@@ -918,7 +918,6 @@ static int config_parse_limit(
 
         struct rlimit **rl = data;
         unsigned long long u;
-        int r;
 
         assert(filename);
         assert(lvalue);
index fc3aac1..117df05 100644 (file)
@@ -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)