Merge lp:~goraxe/upstart/user_sid into lp:upstart

Proposed by goraxe
Status: Rejected
Rejected by: James Hunt
Proposed branch: lp:~goraxe/upstart/user_sid
Merge into: lp:upstart
Diff against target: 631 lines (+469/-2) (has conflicts)
8 files modified
init/job_class.c (+3/-0)
init/job_class.h (+3/-0)
init/job_process.c (+92/-0)
init/job_process.h (+6/-1)
init/parse_job.c (+88/-0)
init/tests/test_job_class.c (+2/-0)
init/tests/test_job_process.c (+50/-1)
init/tests/test_parse_job.c (+225/-0)
Text conflict in init/job_process.c
Text conflict in init/parse_job.c
Text conflict in init/tests/test_job_process.c
To merge this branch: bzr merge lp:~goraxe/upstart/user_sid
Reviewer Review Type Date Requested Status
James Hunt Disapprove
Scott James Remnant (Canonical) Pending
Review via email: mp+59309@code.launchpad.net

This proposal supersedes a proposal from 2010-08-05.

Description of the change

adds a user stanza to the config set, job_process_spawn uses this to setuid before exec-ing

proposing for merge to get feedback/review on code, approach, tests, error handling etc.

Changed target branch as requested

To post a comment you must log in.
Revision history for this message
Johan Kiviniemi (ion) wrote : Posted in a previous version of this proposal

There’s some inconsistent use of whitespace. There also are some superfluous whitespace changes to preexisting code.

Asserting getpwnam doesn’t fail might not be the best thing to do for an init daemon.

The success of the setuid call is not verified.

Revision history for this message
termie (termie) wrote : Posted in a previous version of this proposal

ping?

Revision history for this message
goraxe (goraxe) wrote : Posted in a previous version of this proposal

pong

> -----Original Message-----
> From: <email address hidden> [mailto:<email address hidden>] On Behalf Of
> termie
> Sent: January 12, 2011 1:36 PM
> To: <email address hidden>
> Subject: Re: [Merge] lp:~goraxe/upstart/user_sid into lp:upstart
>
> ping?
> --
> https://code.launchpad.net/~goraxe/upstart/user_sid/+merge/31905
> You are the owner of lp:~goraxe/upstart/user_sid.

Sophos Limited, The Pentagon, Abingdon Science Park, Abingdon, OX14 3YP, United Kingdom.
Company Reg No 2096520. VAT Reg No GB 991 2418 08.

Revision history for this message
Scott James Remnant (scott) wrote : Posted in a previous version of this proposal

At a first pass, this looks ok to me. But I'd like to do another pass or two before approving.

Could you change the proposed branch to be the new lp:upstart to make tracking easier?

Revision history for this message
Scott James Remnant (scott) wrote :

getpwnam() can block for an arbitrary amount of time, which can be hours or weeks (LDAP, network not available, etc.)

it's not acceptable for the init daemon to stall like this

Revision history for this message
goraxe (goraxe) wrote :

I have changed the proposed target branch as requested

Revision history for this message
goraxe (goraxe) wrote :

Is there anything in nih which implements a timeout wrapper or would a SIGALRM signal to wake up and abort make sense?

Revision history for this message
Scott James Remnant (scott) wrote :

Neither makes sense; init would be still blocking for that timeout or until
that SIGALRM call

On Wed, Apr 27, 2011 at 4:32 PM, goraxe <email address hidden> wrote:

> Is there anything in nih which implements a timeout wrapper or would a
> SIGALRM signal to wake up and abort make sense?
> --
> https://code.launchpad.net/~goraxe/upstart/user_sid/+merge/59309
> Your team Upstart Developers is subscribed to branch lp:upstart.
>

Revision history for this message
goraxe (goraxe) wrote :

By the time the getpwnam() has been called, is it not already being performed in the child process? The execvp call just after the uid implies this. So the init daemon is not stalled by the blocking call but execution of the child could be. In that case a timeout death of the child proc would be acceptable if upstart then followed some retry logic.

Revision history for this message
Scott James Remnant (scott) wrote :

The init daemon waits for the child process to succeed in its exec() call
(or fail there on the way)

This is because the child process is a direct copy of the init daemon,
meaning all of the init daemon's memory becomes copy-on-write for the period
where the child exists. If pid 1 did not wait, performance would suffer
massively as processes endured page-fault after page-fault.

It's best to treat the code between the fork() and exec() as still running
in init context

On Wed, Apr 27, 2011 at 4:50 PM, goraxe <email address hidden> wrote:

> By the time the getpwnam() has been called, is it not already being
> performed in the child process? The execvp call just after the uid implies
> this. So the init daemon is not stalled by the blocking call but execution
> of the child could be. In that case a timeout death of the child proc would
> be acceptable if upstart then followed some retry logic.
> --
> https://code.launchpad.net/~goraxe/upstart/user_sid/+merge/59309
> Your team Upstart Developers is subscribed to branch lp:upstart.
>

Revision history for this message
goraxe (goraxe) wrote :

Any thoughts then on getting around the blocking nature of getpwnam?

Revision history for this message
Scott James Remnant (scott) wrote :

I think you'd have to begin the lookups in the background as soon as the job
is parsed, and have a local cache of name to pwnam structure references. If
a lookup fails, you should have a mechanism to retry that lookup later (e.g.
when a network interface comes up).

At the point of starting a job, if the pwnam cache doesn't contain the name,
it should fail to start.

That's how I'd do it, anyway

Scott

On Wed, Apr 27, 2011 at 5:57 PM, goraxe <email address hidden> wrote:

> Any thoughts then on getting around the blocking nature of getpwnam?
> --
> https://code.launchpad.net/~goraxe/upstart/user_sid/+merge/59309
> Your team Upstart Developers is subscribed to branch lp:upstart.
>

Revision history for this message
James Hunt (jamesodhunt) wrote :

Rejecting as Upstart has had the ability to switch user since v1.4: http://upstart.ubuntu.com/cookbook/#setuid

review: Disapprove
Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Hello!

New message, please read <http://okna-blagodat.com/blood.php?md2x0>

<email address hidden>

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Hey,

I've got some good news for you, read more about it here <http://raryndetho.spookpictures.com/score.php?xl6>

Later, <email address hidden>

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Greetings,

Just take a look at that new store, they have so many cool things, they also have a very nice on-line store <http://attach.carnow.ca/lnril>

philipp

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Yo!

Have you read this new book already? I'm so delighted with it, please read it here http://extra.sixpacksoul.com/5958

Hugs, philipp

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Hey,

I'd like to show you a nice gift a friend of mine gave me recently, it's something really cool)) Please take a look http://harjap.com/coach.php?8a8b

Hope this helps, philipp

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Hello,

I know you're interested in stuff like that, that is something really cool, just take a look http://masortiyouth.org/cycle.php?e5e4

Hope this helps, philipp

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Dear,

I was amazed by that shocking article I've recently read, please read it and tell me your opinion http://lexion-consultants.com/vs.php?2120

Warmest regards, philipp

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Hello friend,

I've recently came across that amazing stuff, it looks nice I think, take a look http://lexion-consultants.com/rack.php?a4a5

Yours sincerely, philipp

Revision history for this message
Philipp Schlesinger (philipp-sadleder) wrote : Posted in a previous version of this proposal

Yo!

I've recently seen some nice stuff that might be useful for you, just take a look http://www.tcsoluciones.cl/less.php?1110

My Best, philipp

Unmerged revisions

1247. By goraxe

fix white space

1246. By goraxe

change stanzer to uid, add gid, & initgroups

1245. By goraxe

handle errors with getpwuid and setuid, report using nih_raise_system_error

1244. By goraxe

convert indentation to spaces, minimise white space noise

1243. By goraxe

become the user of the class

1242. By goraxe

set user to null in job_new

1241. By goraxe

add user to parser

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'init/job_class.c'
--- init/job_class.c 2010-12-14 15:30:06 +0000
+++ init/job_class.c 2011-04-27 23:21:25 +0000
@@ -219,6 +219,9 @@
219 class->chroot = NULL;219 class->chroot = NULL;
220 class->chdir = NULL;220 class->chdir = NULL;
221221
222 class->uid = NULL;
223 class->gid = NULL;
224
222 class->deleted = FALSE;225 class->deleted = FALSE;
223 class->debug = FALSE;226 class->debug = FALSE;
224227
225228
=== modified file 'init/job_class.h'
--- init/job_class.h 2010-12-14 15:30:06 +0000
+++ init/job_class.h 2011-04-27 23:21:25 +0000
@@ -98,6 +98,7 @@
98 * @chroot: root directory of process (implies @chdir if not set),98 * @chroot: root directory of process (implies @chdir if not set),
99 * @chdir: working directory of process,99 * @chdir: working directory of process,
100 * @deleted: whether job should be deleted when finished.100 * @deleted: whether job should be deleted when finished.
101 * @uid: holds the name or id of a user who's id should be set via setid
101 *102 *
102 * This structure holds the configuration of a known task or service that103 * This structure holds the configuration of a known task or service that
103 * should be tracked by the init daemon; as tasks and services are104 * should be tracked by the init daemon; as tasks and services are
@@ -146,6 +147,8 @@
146 char *chroot;147 char *chroot;
147 char *chdir;148 char *chdir;
148149
150 char *uid;
151 char *gid;
149 int deleted;152 int deleted;
150 int debug;153 int debug;
151} JobClass;154} JobClass;
152155
=== modified file 'init/job_process.c'
--- init/job_process.c 2011-03-22 17:46:46 +0000
+++ init/job_process.c 2011-04-27 23:21:25 +0000
@@ -39,8 +39,13 @@
39#include <stdlib.h>39#include <stdlib.h>
40#include <string.h>40#include <string.h>
41#include <unistd.h>41#include <unistd.h>
42<<<<<<< TREE
42#include <utmp.h>43#include <utmp.h>
43#include <utmpx.h>44#include <utmpx.h>
45=======
46#include <pwd.h>
47#include <grp.h>
48>>>>>>> MERGE-SOURCE
4449
45#include <nih/macros.h>50#include <nih/macros.h>
46#include <nih/alloc.h>51#include <nih/alloc.h>
@@ -566,6 +571,68 @@
566 }571 }
567 }572 }
568573
574 /* drop privilages */
575 if (class->uid) {
576 struct passwd *pw;
577 uid_t uid;
578 gid_t gid;
579 char *user;
580 /* convet value of uid to numerical form */
581 uid = strtol(class->uid, NULL, 10);
582 /* if failed assume user and lookup via nss */
583 if (uid == 0 && errno == EINVAL) {
584 pw = getpwnam (class->uid);
585 if (pw == NULL) {
586 nih_error_raise_system ();
587 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_USER, 0);
588 }
589 } else {
590 /* we need to lookup real user name */
591 pw = getpwuid (uid);
592 if (pw == NULL) {
593 nih_error_raise_system ();
594 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_USER, 0);
595 }
596 }
597
598 uid = pw->pw_uid;
599 gid = pw->pw_gid;
600 user = pw->pw_name;
601 /* now check to see if we have been given a group */
602 if (class->gid) {
603 struct group *gr;
604
605 gid = strtol(class->gid, NULL, 10);
606 if (gid == 0 && errno == EINVAL) {
607 gr = getgrnam(class->gid);
608 if (gr == NULL) {
609 nih_error_raise_system ();
610 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GROUP, 0);
611 }
612 } else {
613 gr = getgrgid (gid);
614 if (gr == NULL) {
615 nih_error_raise_system ();
616 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GROUP, 0);
617 }
618 }
619
620 gid = gr->gr_gid;
621 }
622 if (setuid (uid) < 0) {
623 nih_error_raise_system ();
624 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
625 }
626 if (setgid (gid) < 0) {
627 nih_error_raise_system ();
628 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
629 }
630 if (initgroups(user, gid) < 0) {
631 nih_error_raise_system ();
632 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_INITGROUPS, 0);
633 }
634 }
635
569 /* Execute the process, if we escape from here it failed */636 /* Execute the process, if we escape from here it failed */
570 if (execvp (argv[0], argv) < 0) {637 if (execvp (argv[0], argv) < 0) {
571 nih_error_raise_system ();638 nih_error_raise_system ();
@@ -754,6 +821,31 @@
754 err, _("unable to execute: %s"),821 err, _("unable to execute: %s"),
755 strerror (err->errnum)));822 strerror (err->errnum)));
756 break;823 break;
824 case JOB_PROCESS_ERROR_USER:
825 err->error.message = NIH_MUST (nih_sprintf (
826 err, _("unable to find user for job: %s"),
827 strerror (err->errnum)));
828 break;
829 case JOB_PROCESS_ERROR_SETUID:
830 err->error.message = NIH_MUST (nih_sprintf (
831 err, _("unable to setuid: %s"),
832 strerror (err->errnum)));
833 break;
834 case JOB_PROCESS_ERROR_SETGID:
835 err->error.message = NIH_MUST (nih_sprintf (
836 err, _("unable to setgid: %s"),
837 strerror (err->errnum)));
838 break;
839 case JOB_PROCESS_ERROR_GROUP:
840 err->error.message = NIH_MUST (nih_sprintf (
841 err, _("unable to find group for job: %s"),
842 strerror (err->errnum)));
843 break;
844 case JOB_PROCESS_ERROR_INITGROUPS:
845 err->error.message = NIH_MUST (nih_sprintf (
846 err, _("unable to initgroups: %s"),
847 strerror (err->errnum)));
848 break;
757 default:849 default:
758 nih_assert_not_reached ();850 nih_assert_not_reached ();
759 }851 }
760852
=== modified file 'init/job_process.h'
--- init/job_process.h 2009-07-09 11:01:53 +0000
+++ init/job_process.h 2011-04-27 23:21:25 +0000
@@ -45,7 +45,12 @@
45 JOB_PROCESS_ERROR_CHROOT,45 JOB_PROCESS_ERROR_CHROOT,
46 JOB_PROCESS_ERROR_CHDIR,46 JOB_PROCESS_ERROR_CHDIR,
47 JOB_PROCESS_ERROR_PTRACE,47 JOB_PROCESS_ERROR_PTRACE,
48 JOB_PROCESS_ERROR_EXEC48 JOB_PROCESS_ERROR_EXEC,
49 JOB_PROCESS_ERROR_USER,
50 JOB_PROCESS_ERROR_GROUP,
51 JOB_PROCESS_ERROR_SETUID,
52 JOB_PROCESS_ERROR_SETGID,
53 JOB_PROCESS_ERROR_INITGROUPS
49} JobProcessErrorType;54} JobProcessErrorType;
5055
51/**56/**
5257
=== modified file 'init/parse_job.c'
--- init/parse_job.c 2011-01-17 16:37:54 +0000
+++ init/parse_job.c 2011-04-27 23:21:25 +0000
@@ -218,6 +218,14 @@
218 size_t *pos, size_t *lineno)218 size_t *pos, size_t *lineno)
219 __attribute__ ((warn_unused_result));219 __attribute__ ((warn_unused_result));
220220
221static int stanza_uid (JobClass *class, NihConfigStanza *stanza,
222 const char *file, size_t len,
223 size_t *pos, size_t *lineno)
224 __attribute__ ((warn_unused_result));
225static int stanza_gid (JobClass *class, NihConfigStanza *stanza,
226 const char *file, size_t len,
227 size_t *pos, size_t *lineno)
228 __attribute__ ((warn_unused_result));
221229
222/**230/**
223 * stanzas:231 * stanzas:
@@ -253,8 +261,13 @@
253 { "limit", (NihConfigHandler)stanza_limit },261 { "limit", (NihConfigHandler)stanza_limit },
254 { "chroot", (NihConfigHandler)stanza_chroot },262 { "chroot", (NihConfigHandler)stanza_chroot },
255 { "chdir", (NihConfigHandler)stanza_chdir },263 { "chdir", (NihConfigHandler)stanza_chdir },
264<<<<<<< TREE
256 { "debug", (NihConfigHandler)stanza_debug },265 { "debug", (NihConfigHandler)stanza_debug },
257 { "manual", (NihConfigHandler)stanza_manual },266 { "manual", (NihConfigHandler)stanza_manual },
267=======
268 { "uid", (NihConfigHandler)stanza_uid },
269 { "gid", (NihConfigHandler)stanza_gid },
270>>>>>>> MERGE-SOURCE
258271
259 NIH_CONFIG_LAST272 NIH_CONFIG_LAST
260};273};
@@ -2472,3 +2485,78 @@
24722485
2473 return nih_config_skip_comment (file, len, pos, lineno);2486 return nih_config_skip_comment (file, len, pos, lineno);
2474}2487}
2488
2489
2490/**
2491 * stanza_uid:
2492 * @class: job class being parsed,
2493 * @stanza: stanza found,
2494 * @file: file or string to parse,
2495 * @len: length of @file,
2496 * @pos: offset within @file,
2497 * @lineno: line number.
2498 *
2499 * Parse a user stanza from @file, extracting a single argument
2500 * containing a user to drop priviagles to.
2501 *
2502 * Returns: zero on success, negative value on error.
2503 **/
2504static int
2505stanza_uid (JobClass *class,
2506 NihConfigStanza *stanza,
2507 const char *file,
2508 size_t len,
2509 size_t *pos,
2510 size_t *lineno)
2511{
2512 nih_assert (class != NULL);
2513 nih_assert (stanza != NULL);
2514 nih_assert (file != NULL);
2515 nih_assert (pos != NULL);
2516
2517 if (class->uid)
2518 nih_unref (class->uid, class);
2519 /* FIXME lookup uid */
2520 class->uid = nih_config_next_arg (class, file, len, pos, lineno);
2521 if (! class->uid)
2522 return -1;
2523
2524 return nih_config_skip_comment (file, len, pos, lineno);
2525}
2526
2527/**
2528 * stanza_gid:
2529 * @class: job class being parsed,
2530 * @stanza: stanza found,
2531 * @file: file or string to parse,
2532 * @len: length of @file,
2533 * @pos: offset within @file,
2534 * @lineno: line number.
2535 *
2536 * Parse a gid stanza from @file, extracting a single argument
2537 * containing a group to drop priviagles to.
2538 *
2539 * Returns: zero on success, negative value on error.
2540 **/
2541static int
2542stanza_gid (JobClass *class,
2543 NihConfigStanza *stanza,
2544 const char *file,
2545 size_t len,
2546 size_t *pos,
2547 size_t *lineno)
2548{
2549 nih_assert (class != NULL);
2550 nih_assert (stanza != NULL);
2551 nih_assert (file != NULL);
2552 nih_assert (pos != NULL);
2553
2554 if (class->gid)
2555 nih_unref (class->gid, class);
2556
2557 class->gid = nih_config_next_arg (class, file, len, pos, lineno);
2558 if (! class->gid)
2559 return -1;
2560
2561 return nih_config_skip_comment (file, len, pos, lineno);
2562}
24752563
=== modified file 'init/tests/test_job_class.c'
--- init/tests/test_job_class.c 2011-03-16 22:42:48 +0000
+++ init/tests/test_job_class.c 2011-04-27 23:21:25 +0000
@@ -140,6 +140,8 @@
140140
141 TEST_EQ_P (class->chroot, NULL);141 TEST_EQ_P (class->chroot, NULL);
142 TEST_EQ_P (class->chdir, NULL);142 TEST_EQ_P (class->chdir, NULL);
143 TEST_EQ_P (class->uid, NULL);
144 TEST_EQ_P (class->gid, NULL);
143 TEST_FALSE (class->deleted);145 TEST_FALSE (class->deleted);
144146
145 nih_free (class);147 nih_free (class);
146148
=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c 2011-03-16 22:18:22 +0000
+++ init/tests/test_job_process.c 2011-04-27 23:21:25 +0000
@@ -37,8 +37,12 @@
37#include <stdlib.h>37#include <stdlib.h>
38#include <string.h>38#include <string.h>
39#include <unistd.h>39#include <unistd.h>
40<<<<<<< TREE
40#include <utmp.h>41#include <utmp.h>
41#include <utmpx.h>42#include <utmpx.h>
43=======
44#include <pwd.h>
45>>>>>>> MERGE-SOURCE
4246
43#include <nih/macros.h>47#include <nih/macros.h>
44#include <nih/string.h>48#include <nih/string.h>
@@ -66,7 +70,8 @@
66 TEST_PIDS,70 TEST_PIDS,
67 TEST_CONSOLE,71 TEST_CONSOLE,
68 TEST_PWD,72 TEST_PWD,
69 TEST_ENVIRONMENT73 TEST_ENVIRONMENT,
74 TEST_USER
70};75};
7176
72static char *argv0;77static char *argv0;
@@ -78,6 +83,8 @@
78 FILE *out;83 FILE *out;
79 char tmpname[PATH_MAX], path[PATH_MAX];84 char tmpname[PATH_MAX], path[PATH_MAX];
80 int i;85 int i;
86 struct passwd *pw;
87 int uid;
8188
82 strcpy (tmpname, filename);89 strcpy (tmpname, filename);
83 strcat (tmpname, ".tmp");90 strcat (tmpname, ".tmp");
@@ -107,6 +114,15 @@
107 assert (getcwd (path, sizeof (path)));114 assert (getcwd (path, sizeof (path)));
108 fprintf (out, "wd: %s\n", path);115 fprintf (out, "wd: %s\n", path);
109 break;116 break;
117 case TEST_USER:
118 /* get our id */
119 uid = getuid();
120
121 /* find this users passwd record */
122 pw = getpwuid(uid);
123 assert(pw != NULL);
124 fprintf(out, "user: %s\n", pw->pw_name);
125 break;
110 case TEST_ENVIRONMENT:126 case TEST_ENVIRONMENT:
111 for (char **env = environ; *env; env++)127 for (char **env = environ; *env; env++)
112 fprintf (out, "%s\n", *env);128 fprintf (out, "%s\n", *env);
@@ -901,6 +917,39 @@
901 nih_free (class);917 nih_free (class);
902918
903919
920 /* Check that a job with a specified user runs as that user, requires
921 * root privs to run
922 */
923 TEST_FEATURE ("with user");
924 sprintf (function, "%d", TEST_USER);
925
926 class = job_class_new(NULL, "test");
927
928 struct passwd *pw;
929 int uid;
930 /* get our id */
931 uid = getuid();
932
933 /* find this users passwd record */
934 pw = getpwuid(uid);
935 class->uid = nih_strdup(class, pw->pw_name);
936
937
938 pid = job_process_spawn (class, args, NULL, FALSE);
939 TEST_GT(pid,0);
940
941 waitpid (pid, NULL, 0);
942
943 output = fopen (filename, "r");
944
945 sprintf(buf, "user: %s\n", pw->pw_name);
946 TEST_FILE_EQ (output, buf);
947 TEST_FILE_END (output);
948
949 fclose (output);
950 unlink (filename);
951
952 nih_free (class);
904 /* Check that a job is run with only the environment variables953 /* Check that a job is run with only the environment variables
905 * specifiec in the function call.954 * specifiec in the function call.
906 */955 */
907956
=== modified file 'init/tests/test_parse_job.c'
--- init/tests/test_parse_job.c 2010-12-14 16:20:38 +0000
+++ init/tests/test_parse_job.c 2011-04-27 23:21:25 +0000
@@ -7493,6 +7493,230 @@
7493 nih_free (err);7493 nih_free (err);
7494}7494}
74957495
7496void
7497test_stanza_uid(void)
7498{
7499 JobClass*job;
7500 NihError *err;
7501 size_t pos, lineno;
7502 char buf[1024];
7503
7504 TEST_FUNCTION ("stanza_uid");
7505
7506 /* Check that a uid stanza with an argument results in it
7507 * being stored in the job.
7508 */
7509 TEST_FEATURE ("with single argument");
7510 strcpy (buf, "uid nobody\n");
7511
7512 TEST_ALLOC_FAIL {
7513 pos = 0;
7514 lineno = 1;
7515 job = parse_job (NULL, "test", buf, strlen (buf),
7516 &pos, &lineno);
7517 if (test_alloc_failed) {
7518 TEST_EQ_P (job, NULL);
7519
7520 err = nih_error_get ();
7521 TEST_EQ (err->number, ENOMEM);
7522 nih_free (err);
7523
7524 continue;
7525 }
7526 TEST_EQ (pos, strlen (buf));
7527 TEST_EQ (lineno, 2);
7528
7529 TEST_ALLOC_SIZE (job, sizeof (JobClass));
7530
7531 TEST_ALLOC_PARENT (job->uid, job);
7532 TEST_EQ_STR (job->uid, "nobody");
7533 nih_free (job);
7534 }
7535
7536 /* Check that the last of multiple uid stanzas is used.
7537 */
7538 TEST_FEATURE ("with multiple stanzas");
7539 strcpy (buf, "uid nobody\n");
7540 strcat (buf, "uid gordon\n");
7541
7542 TEST_ALLOC_FAIL {
7543 pos = 0;
7544 lineno = 1;
7545 job = parse_job (NULL, "test", buf, strlen (buf),
7546 &pos, &lineno);
7547
7548 if (test_alloc_failed) {
7549 TEST_EQ_P (job, NULL);
7550
7551 err = nih_error_get ();
7552 TEST_EQ (err->number, ENOMEM);
7553 nih_free (err);
7554
7555 continue;
7556 }
7557
7558 TEST_EQ (pos, strlen (buf));
7559 TEST_EQ (lineno, 3);
7560
7561 TEST_ALLOC_SIZE (job, sizeof (JobClass));
7562
7563 TEST_ALLOC_PARENT (job->uid, job);
7564 TEST_EQ_STR (job->uid, "gordon");
7565
7566 nih_free (job);
7567 }
7568
7569
7570 /* Check that a uid stanza without an argument results in
7571 * a syntax error.
7572 */
7573 TEST_FEATURE ("with missing argument");
7574 strcpy (buf, "uid\n");
7575
7576 pos = 0;
7577 lineno = 1;
7578 job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
7579
7580 TEST_EQ_P (job, NULL);
7581
7582 err = nih_error_get ();
7583 TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN);
7584 TEST_EQ (pos, 3);
7585 TEST_EQ (lineno, 1);
7586 nih_free (err);
7587
7588
7589 /* Check that a uid stanza with an extra second argument
7590 * results in a syntax error.
7591 */
7592 TEST_FEATURE ("with extra argument");
7593 strcpy (buf, "uid bar foo\n");
7594
7595 pos = 0;
7596 lineno = 1;
7597 job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
7598
7599 TEST_EQ_P (job, NULL);
7600
7601 err = nih_error_get ();
7602 TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN);
7603 TEST_EQ (pos, 8);
7604 TEST_EQ (lineno, 1);
7605 nih_free (err);
7606}
7607
7608void
7609test_stanza_gid(void)
7610{
7611 JobClass*job;
7612 NihError *err;
7613 size_t pos, lineno;
7614 char buf[1024];
7615
7616 TEST_FUNCTION ("stanza_gid");
7617
7618 /* Check that a gid stanza with an argument results in it
7619 * being stored in the job.
7620 */
7621 TEST_FEATURE ("with single argument");
7622 strcpy (buf, "gid nobody\n");
7623
7624 TEST_ALLOC_FAIL {
7625 pos = 0;
7626 lineno = 1;
7627 job = parse_job (NULL, "test", buf, strlen (buf),
7628 &pos, &lineno);
7629 if (test_alloc_failed) {
7630 TEST_EQ_P (job, NULL);
7631
7632 err = nih_error_get ();
7633 TEST_EQ (err->number, ENOMEM);
7634 nih_free (err);
7635
7636 continue;
7637 }
7638 TEST_EQ (pos, strlen (buf));
7639 TEST_EQ (lineno, 2);
7640
7641 TEST_ALLOC_SIZE (job, sizeof (JobClass));
7642
7643 TEST_ALLOC_PARENT (job->gid, job);
7644 TEST_EQ_STR (job->gid, "nobody");
7645 nih_free (job);
7646 }
7647
7648 /* Check that the last of multiple gid stanzas is used.
7649 */
7650 TEST_FEATURE ("with multiple stanzas");
7651 strcpy (buf, "gid nobody\n");
7652 strcat (buf, "gid gordon\n");
7653
7654 TEST_ALLOC_FAIL {
7655 pos = 0;
7656 lineno = 1;
7657 job = parse_job (NULL, "test", buf, strlen (buf),
7658 &pos, &lineno);
7659
7660 if (test_alloc_failed) {
7661 TEST_EQ_P (job, NULL);
7662
7663 err = nih_error_get ();
7664 TEST_EQ (err->number, ENOMEM);
7665 nih_free (err);
7666
7667 continue;
7668 }
7669
7670 TEST_EQ (pos, strlen (buf));
7671 TEST_EQ (lineno, 3);
7672
7673 TEST_ALLOC_SIZE (job, sizeof (JobClass));
7674
7675 TEST_ALLOC_PARENT (job->gid, job);
7676 TEST_EQ_STR (job->gid, "gordon");
7677
7678 nih_free (job);
7679 }
7680
7681
7682 /* Check that a gid stanza without an argument results in
7683 * a syntax error.
7684 */
7685 TEST_FEATURE ("with missing argument");
7686 strcpy (buf, "gid\n");
7687
7688 pos = 0;
7689 lineno = 1;
7690 job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
7691
7692 TEST_EQ_P (job, NULL);
7693
7694 err = nih_error_get ();
7695 TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN);
7696 TEST_EQ (pos, 3);
7697 TEST_EQ (lineno, 1);
7698 nih_free (err);
7699
7700
7701 /* Check that a gid stanza with an extra second argument
7702 * results in a syntax error.
7703 */
7704 TEST_FEATURE ("with extra argument");
7705 strcpy (buf, "gid bar foo\n");
7706
7707 pos = 0;
7708 lineno = 1;
7709 job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
7710
7711 TEST_EQ_P (job, NULL);
7712
7713 err = nih_error_get ();
7714 TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN);
7715 TEST_EQ (pos, 8);
7716 TEST_EQ (lineno, 1);
7717 nih_free (err);
7718}
7719
7496int7720int
7497main (int argc,7721main (int argc,
7498 char *argv[])7722 char *argv[])
@@ -7535,6 +7759,7 @@
7535 test_stanza_oom ();7759 test_stanza_oom ();
7536 test_stanza_limit ();7760 test_stanza_limit ();
7537 test_stanza_chroot ();7761 test_stanza_chroot ();
7762 test_stanza_uid();
7538 test_stanza_chdir ();7763 test_stanza_chdir ();
75397764
7540 return 0;7765 return 0;

Subscribers

People subscribed via source and target branches