701
702
close (pty_slave);
704
/* Set resource limits for the process, skipping over any that
705
* aren't set in the job class such that they inherit from
706
* ourselves (and we inherit from kernel defaults).
705
/* Switch to the specified AppArmor profile, but only for the main
706
process, so we don't confine the pre- and post- processes.
708
for (i = 0; i < RLIMIT_NLIMITS; i++) {
709
if (! class->limits[i])
712
if (setrlimit (i, class->limits[i]) < 0) {
708
if ((class->apparmor_switch) && (process == PROCESS_MAIN)) {
709
nih_local char *profile = NULL;
711
/* Use the environment to expand the AppArmor profile name
713
profile = NIH_SHOULD (environ_expand (NULL,
714
class->apparmor_switch,
718
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SECURITY, 0);
721
if (apparmor_switch (profile) < 0) {
722
nih_error_raise_system ();
723
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SECURITY, 0);
727
if (process != PROCESS_SECURITY) {
728
/* Set resource limits for the process, skipping over any that
729
* aren't set in the job class such that they inherit from
730
* ourselves (and we inherit from kernel defaults).
732
for (i = 0; i < RLIMIT_NLIMITS; i++) {
733
if (! class->limits[i])
736
if (setrlimit (i, class->limits[i]) < 0) {
737
nih_error_raise_system ();
738
job_process_error_abort (fds[1],
739
JOB_PROCESS_ERROR_RLIMIT, i);
743
/* Set the file mode creation mask; this is one of the few operations
744
* that can never fail.
746
umask (class->umask);
748
/* Adjust the process priority ("nice level").
750
if (class->nice != JOB_NICE_INVALID &&
751
setpriority (PRIO_PROCESS, 0, class->nice) < 0) {
713
752
nih_error_raise_system ();
714
753
job_process_error_abort (fds[1],
715
JOB_PROCESS_ERROR_RLIMIT, i);
754
JOB_PROCESS_ERROR_PRIORITY, 0);
719
/* Set the file mode creation mask; this is one of the few operations
720
* that can never fail.
722
umask (class->umask);
724
/* Adjust the process priority ("nice level").
726
if (class->nice != JOB_NICE_INVALID &&
727
setpriority (PRIO_PROCESS, 0, class->nice) < 0) {
728
nih_error_raise_system ();
729
job_process_error_abort (fds[1],
730
JOB_PROCESS_ERROR_PRIORITY, 0);
733
/* Adjust the process OOM killer priority.
735
if (class->oom_score_adj != JOB_DEFAULT_OOM_SCORE_ADJ) {
737
snprintf (filename, sizeof (filename),
738
"/proc/%d/oom_score_adj", getpid ());
739
oom_value = class->oom_score_adj;
740
fd = fopen (filename, "w");
741
if ((! fd) && (errno == ENOENT)) {
757
/* Adjust the process OOM killer priority.
759
if (class->oom_score_adj != JOB_DEFAULT_OOM_SCORE_ADJ) {
742
761
snprintf (filename, sizeof (filename),
743
"/proc/%d/oom_adj", getpid ());
744
oom_value = (class->oom_score_adj
745
* ((class->oom_score_adj < 0) ? 17 : 15)) / 1000;
762
"/proc/%d/oom_score_adj", getpid ());
763
oom_value = class->oom_score_adj;
746
764
fd = fopen (filename, "w");
749
nih_error_raise_system ();
750
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);
752
fprintf (fd, "%d\n", oom_value);
765
if ((! fd) && (errno == ENOENT)) {
766
snprintf (filename, sizeof (filename),
767
"/proc/%d/oom_adj", getpid ());
768
oom_value = (class->oom_score_adj
769
* ((class->oom_score_adj < 0) ? 17 : 15)) / 1000;
770
fd = fopen (filename, "w");
755
773
nih_error_raise_system ();
756
774
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);
761
/* Handle changing a chroot session job prior to dealing with
762
* the 'chroot' stanza.
764
if (class->session && class->session->chroot) {
765
if (chroot (class->session->chroot) < 0) {
766
nih_error_raise_system ();
767
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHROOT, 0);
771
/* Change the root directory, confining path resolution within it;
772
* we do this before the working directory call so that is always
773
* relative to the new root.
776
if (chroot (class->chroot) < 0) {
777
nih_error_raise_system ();
778
job_process_error_abort (fds[1],
779
JOB_PROCESS_ERROR_CHROOT, 0);
783
/* Change the working directory of the process, either to the one
784
* configured in the job, or to the root directory of the filesystem
785
* (or at least relative to the chroot).
787
if (class->chdir || user_mode == FALSE) {
788
if (chdir (class->chdir ? class->chdir : "/") < 0) {
789
nih_error_raise_system ();
790
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHDIR, 0);
794
/* Change the user and group of the process to the one
795
* configured in the job. We must wait until now to lookup the
796
* UID and GID from the names to accommodate both chroot
797
* session jobs and jobs with a chroot stanza.
800
/* Without resetting errno, it's impossible to
801
* distinguish between a non-existent user and and
802
* error during lookup */
804
pwd = getpwnam (class->setuid);
807
nih_error_raise_system ();
808
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWNAM, 0);
810
nih_error_raise (JOB_PROCESS_INVALID_SETUID,
811
JOB_PROCESS_INVALID_SETUID_STR);
812
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_BAD_SETUID, 0);
816
job_setuid = pwd->pw_uid;
817
/* This will be overridden if setgid is also set: */
818
job_setgid = pwd->pw_gid;
823
grp = getgrnam (class->setgid);
826
nih_error_raise_system ();
827
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRNAM, 0);
829
nih_error_raise (JOB_PROCESS_INVALID_SETGID,
830
JOB_PROCESS_INVALID_SETGID_STR);
831
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_BAD_SETGID, 0);
835
job_setgid = grp->gr_gid;
838
if (script_fd != -1 &&
839
(job_setuid != (uid_t) -1 || job_setgid != (gid_t) -1) &&
840
fchown (script_fd, job_setuid, job_setgid) < 0) {
841
nih_error_raise_system ();
842
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHOWN, 0);
845
/* Make sure we always have the needed pwd and grp structs.
846
* Then pass those to initgroups() to setup the user's group list.
847
* Only do that if we're root as initgroups() won't work when non-root. */
848
if (geteuid () == 0) {
850
pwd = getpwuid (geteuid ());
852
nih_error_raise_system ();
853
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWUID, 0);
858
grp = getgrgid (getegid ());
860
nih_error_raise_system ();
861
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRGID, 0);
866
if (initgroups (pwd->pw_name, grp->gr_gid) < 0) {
867
nih_error_raise_system ();
868
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_INITGROUPS, 0);
873
/* Start dropping privileges */
874
if (job_setgid != (gid_t) -1 && setgid (job_setgid) < 0) {
875
nih_error_raise_system ();
876
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
879
if (job_setuid != (uid_t)-1 && setuid (job_setuid) < 0) {
880
nih_error_raise_system ();
881
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
776
fprintf (fd, "%d\n", oom_value);
779
nih_error_raise_system ();
780
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);
785
/* Handle changing a chroot session job prior to dealing with
786
* the 'chroot' stanza.
788
if (class->session && class->session->chroot) {
789
if (chroot (class->session->chroot) < 0) {
790
nih_error_raise_system ();
791
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHROOT, 0);
795
/* Change the root directory, confining path resolution within it;
796
* we do this before the working directory call so that is always
797
* relative to the new root.
800
if (chroot (class->chroot) < 0) {
801
nih_error_raise_system ();
802
job_process_error_abort (fds[1],
803
JOB_PROCESS_ERROR_CHROOT, 0);
807
/* Change the working directory of the process, either to the one
808
* configured in the job, or to the root directory of the filesystem
809
* (or at least relative to the chroot).
811
if (class->chdir || user_mode == FALSE) {
812
if (chdir (class->chdir ? class->chdir : "/") < 0) {
813
nih_error_raise_system ();
814
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHDIR, 0);
818
/* Change the user and group of the process to the one
819
* configured in the job. We must wait until now to lookup the
820
* UID and GID from the names to accommodate both chroot
821
* session jobs and jobs with a chroot stanza.
824
/* Without resetting errno, it's impossible to
825
* distinguish between a non-existent user and and
826
* error during lookup */
828
pwd = getpwnam (class->setuid);
831
nih_error_raise_system ();
832
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWNAM, 0);
834
nih_error_raise (JOB_PROCESS_INVALID_SETUID,
835
JOB_PROCESS_INVALID_SETUID_STR);
836
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_BAD_SETUID, 0);
840
job_setuid = pwd->pw_uid;
841
/* This will be overridden if setgid is also set: */
842
job_setgid = pwd->pw_gid;
847
grp = getgrnam (class->setgid);
850
nih_error_raise_system ();
851
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRNAM, 0);
853
nih_error_raise (JOB_PROCESS_INVALID_SETGID,
854
JOB_PROCESS_INVALID_SETGID_STR);
855
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_BAD_SETGID, 0);
859
job_setgid = grp->gr_gid;
862
if (script_fd != -1 &&
863
(job_setuid != (uid_t) -1 || job_setgid != (gid_t) -1) &&
864
fchown (script_fd, job_setuid, job_setgid) < 0) {
865
nih_error_raise_system ();
866
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHOWN, 0);
869
/* Make sure we always have the needed pwd and grp structs.
870
* Then pass those to initgroups() to setup the user's group list.
871
* Only do that if we're root as initgroups() won't work when non-root. */
872
if (geteuid () == 0) {
874
pwd = getpwuid (geteuid ());
876
nih_error_raise_system ();
877
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWUID, 0);
882
grp = getgrgid (getegid ());
884
nih_error_raise_system ();
885
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRGID, 0);
890
if (initgroups (pwd->pw_name, grp->gr_gid) < 0) {
891
nih_error_raise_system ();
892
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_INITGROUPS, 0);
897
/* Start dropping privileges */
898
if (job_setgid != (gid_t) -1 && setgid (job_setgid) < 0) {
899
nih_error_raise_system ();
900
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
903
if (job_setuid != (uid_t)-1 && setuid (job_setuid) < 0) {
904
nih_error_raise_system ();
905
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
884
909
/* Reset all the signal handlers back to their default handling so