From 5054878c415b21ba818869394aea9fbe0bcdfdf3 Mon Sep 17 00:00:00 2001 From: Kunhoon Baik Date: Thu, 17 Nov 2016 16:26:34 +0900 Subject: Change MainPID of user@service systemd-user-helper helps to launch systemd user session. Thus, MainPID should be changed to systemd user session for keeping original behavior like stop operation. This patch changes the MainPID to systemd user session by using pidfile and forking type. Change-Id: Id8dc3daa71c18914b79e218043705fe5e167d14f --- packaging/system-plugin.spec | 7 +-- src/systemd-user-helper/systemd-user-helper.c | 77 +++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/packaging/system-plugin.spec b/packaging/system-plugin.spec index 3622003..13684a2 100644 --- a/packaging/system-plugin.spec +++ b/packaging/system-plugin.spec @@ -308,12 +308,13 @@ mv %{_sysconfdir}/fstab_lazymnt %{_sysconfdir}/fstab %manifest systemd-user-helper.manifest %caps(cap_sys_admin,cap_mac_admin,cap_mac_override,cap_dac_override,cap_setgid=ei) %{_bindir}/systemd_user_helper +#TODO: when uninstalling, it should be restored to original file %posttrans -n systemd-user-helper cp -a /usr/lib/systemd/system/user\@.service /usr/lib/systemd/system/__user@.service -/usr/bin/sed -i -e 's/Type=\(.*\)/Type=simple/' /usr/lib/systemd/system/user\@.service +/usr/bin/sed -i -e 's/Type=\(.*\)/Type=forking/' /usr/lib/systemd/system/user\@.service /usr/bin/sed -i -e 's/ExecStart=\(.*\)/ExecStart=\/usr\/bin\/systemd_user_helper %i/' /usr/lib/systemd/system/user\@.service -/usr/bin/sed -i -e '/RemainAfterExit=\(.*\)/d' /usr/lib/systemd/system/user\@.service -echo 'RemainAfterExit=yes' >> /usr/lib/systemd/system/user\@.service +/usr/bin/sed -i -e '/PIDFile=\(.*\)/d' /usr/lib/systemd/system/user\@.service +echo 'PIDFile=/run/user/%i/.systemd.pid' >> /usr/lib/systemd/system/user\@.service %files profile_ivi %{_prefix}/lib/udev/rules.d/99-usb-ethernet.rules diff --git a/src/systemd-user-helper/systemd-user-helper.c b/src/systemd-user-helper/systemd-user-helper.c index a5e22e0..a61a90d 100644 --- a/src/systemd-user-helper/systemd-user-helper.c +++ b/src/systemd-user-helper/systemd-user-helper.c @@ -19,13 +19,19 @@ #include #include #include +#include #include +#include +#include #include #include #include +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) +#define PIDFILE_PATH ".systemd.pid" + // For compatibility, Using hard-coded path #define LEGACY_CONTENTS_DIR "/opt/usr/media" #define LEGACY_APPS_DIR "/opt/usr/apps" @@ -34,7 +40,7 @@ #define CONTAINER_LIB "/usr/lib/security/pam_krate.so" #define LOAD_SYMBOL(handle, sym, name) \ - do{ \ + do { \ sym = dlsym(handle, name); \ if (!sym) { \ fprintf(stderr, "dlsym %s error\n", name); \ @@ -45,18 +51,24 @@ static void *container_handle = NULL; +static const char *systemd_arg[] = { + "/usr/lib/systemd/systemd", + "--user", + NULL +}; + static int normal_user_preprocess(char *username) { int r; r = unshare(CLONE_NEWNS); if (r < 0) { - fprintf(stderr,"unshare failed\n"); + fprintf(stderr, "unshare failed\n"); return r; } r = mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL); if (r < 0) { - fprintf(stderr,"Failed to change the propagation type of root to SLAVE\n"); + fprintf(stderr, "Failed to change the propagation type of root to SLAVE\n"); return r; } @@ -69,14 +81,14 @@ static int normal_user_postprocess(char *username) r = mount(tzplatform_getenv(TZ_USER_CONTENT), LEGACY_CONTENTS_DIR, NULL, MS_BIND, NULL); if (r < 0) { - fprintf(stderr, "user content bind mount failed - %d\n",errno); + fprintf(stderr, "user content bind mount failed - %d\n", errno); return r; } r = mount(tzplatform_getenv(TZ_USER_APP), LEGACY_APPS_DIR, NULL, MS_BIND, NULL); if (r < 0) { - fprintf(stderr, "user app bind mount failed - %d\n",errno); + fprintf(stderr, "user app bind mount failed - %d\n", errno); return r; } @@ -143,8 +155,8 @@ static int wait_condition(void) int (*wait_mount_user)(void); - r = access(LAZYMOUNT_LIB,F_OK); - if (r < 0){ + r = access(LAZYMOUNT_LIB, F_OK); + if (r < 0) { fprintf(stderr, "cannot find lazymount module - No support lazymount\n"); return 0; } @@ -168,6 +180,52 @@ static int wait_condition(void) return 0; } +static int make_pid_file(int pid, char* user_id) +{ + FILE *fp; + char pidpath[PATH_MAX]; + int r = 0; + + snprintf(pidpath, PATH_MAX, "/run/user/%s/%s", user_id, PIDFILE_PATH); + + fp = fopen(pidpath, "w+"); + if (fp != NULL) { + fprintf(fp, "%d", pid); + fclose(fp); + } else + r = -1; + + return r; +} + +int run_child(int argc, const char *argv[], char* user_id) +{ + pid_t pid; + int r = 0; + int i; + + if (!argv) + return -EINVAL; + + pid = fork(); + + if (pid < 0) { + fprintf(stderr, "failed to fork"); + r = -errno; + } else if (pid == 0) { + for (i = 0; i < _NSIG; ++i) + signal(i, SIG_DFL); + + r = execv(argv[0], (char **)argv); + /* NOT REACH */ + } else{ + make_pid_file(pid, user_id); + r = pid; + } + + return r; +} + int main(int argc, char *argv[]) { int r = 0; @@ -195,11 +253,12 @@ int main(int argc, char *argv[]) } } - /* TODO: fork & exec */ - r = system("/usr/lib/systemd/systemd --user &"); + r = run_child(ARRAY_SIZE(systemd_arg), systemd_arg, argv[1]); if (r < 0) { fprintf(stderr, "systemd user execution failed\n"); return r; + } else{ + fprintf(stderr, "success = pid = %d\n", r); } /* sync-style since there is no need to process other signal */ -- cgit v1.2.3