/[smeserver]/rpms/sudo/sme9/sudo-1.8.6p3-sudoedit-selinux.patch
ViewVC logotype

Annotation of /rpms/sudo/sme9/sudo-1.8.6p3-sudoedit-selinux.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download)
Thu Feb 4 19:44:42 2021 UTC (3 years, 4 months ago) by jpp
Branch: MAIN
CVS Tags: sudo-1_8_6p3-30_el6_sme, sudo-1_8_6p3-29_el6_9, HEAD
Sudo

1 jpp 1.1 diff -up sudo-1.8.6p3/src/sesh.c.sudoedit-selinux sudo-1.8.6p3/src/sesh.c
2     --- sudo-1.8.6p3/src/sesh.c.sudoedit-selinux 2012-09-18 15:56:30.000000000 +0200
3     +++ sudo-1.8.6p3/src/sesh.c 2012-09-25 16:06:33.408584649 +0200
4     @@ -34,6 +34,10 @@
5     # include "compat/stdbool.h"
6     #endif /* HAVE_STDBOOL_H */
7    
8     +#include <sys/stat.h>
9     +#include <fcntl.h>
10     +#include <errno.h>
11     +
12     #include "missing.h"
13     #include "alloc.h"
14     #include "error.h"
15     @@ -43,6 +47,16 @@
16     #include "sudo_exec.h"
17     #include "sudo_plugin.h"
18    
19     +/*
20     + * Return codes:
21     + * EXIT_FAILURE ... unspecified error
22     + * 0 ... everything ok
23     + * 30 ... invalid -e arg value
24     + * 31 ... odd number of paths
25     + * 32 ... copy operation failed, no files copied
26     + * 33 ... copy operation failed, some files copied
27     + */
28     +
29     sudo_conv_t sudo_conv; /* NULL in non-plugin */
30    
31     /*
32     @@ -77,19 +91,134 @@ main(int argc, char *argv[], char *envp[
33     if ((cp = strrchr(argv[0], '-')) != NULL && cp != argv[0])
34     noexec = strcmp(cp, "-noexec") == 0;
35    
36     - /* Shift argv and make a copy of the command to execute. */
37     - argv++;
38     - argc--;
39     - cmnd = estrdup(argv[0]);
40     -
41     - /* If invoked as a login shell, modify argv[0] accordingly. */
42     - if (argv[-1][0] == '-') {
43     - if ((cp = strrchr(argv[0], '/')) == NULL)
44     - cp = argv[0];
45     - *cp = '-';
46     + /* check the first argument, if it's `-e' then we are in sudoedit mode */
47     + if (strncmp(argv[1], "-e", 3) == 0) {
48     + int fd_src, fd_dst, post, n, ret = -1;
49     + ssize_t nread, nwritten;
50     + char *path_src, *path_dst, buf[BUFSIZ];
51     +
52     + if (argc < 3)
53     + return EXIT_FAILURE;
54     +
55     + /*
56     + * We need to know whether we are performing the copy operation
57     + * before or after the editing. Without this we would not know
58     + * which files are temporary and which are the originals.
59     + * post = 0 ... before
60     + * post = 1 ... after
61     + */
62     + if (strncmp(argv[2], "0", 2) == 0)
63     + post = 0;
64     + else if (strncmp(argv[2], "1", 2) == 0)
65     + post = 1;
66     + else /* invalid value */
67     + return 30;
68     +
69     + /* align argv & argc to the beggining of the file list */
70     + argv += 3;
71     + argc -= 3;
72     +
73     + /* no files specified, nothing to do */
74     + if (argc == 0)
75     + return 0;
76     + /* odd number of paths specified */
77     + if (argc % 2 == 1)
78     + return 31;
79     +
80     + for (n = 0; n < argc - 1; n += 2) {
81     + path_src = argv[n];
82     + path_dst = argv[n+1];
83     + /*
84     + * Try to open the source file for reading. If it
85     + * doesn't exist, it's ok, we'll create an empty
86     + * destination file.
87     + */
88     + if ((fd_src = open(path_src, O_RDONLY, 0600)) < 0) {
89     + if (errno == ENOENT) {
90     + /* new file */
91     + } else {
92     + warning(_("open(%s)"), path_src);
93     + if (post) {
94     + ret = 33;
95     + goto nocleanup;
96     + } else
97     + goto cleanup_0;
98     + }
99     + }
100     +
101     + /*
102     + * Use O_EXCL if we are not in the post editing stage
103     + * so that it's ensured that the temporary files are
104     + * created by us and that we are not opening any sym-
105     + * links.
106     + */
107     + if ((fd_dst = open(path_dst, (post ? 0 : O_EXCL) |
108     + O_WRONLY|O_TRUNC|O_CREAT, post ? 0644 : 0600)) < 0)
109     + {
110     + /* error - cleanup */
111     + warning(_("open(%s%s)"), path_dst, post ? "" : ", O_EXCL");
112     + if (post) {
113     + ret = 33;
114     + goto nocleanup;
115     + } else
116     + goto cleanup_0;
117     + }
118     +
119     + if (fd_src != -1) {
120     + while ((nread = read(fd_src, buf, sizeof(buf))) > 0) {
121     + if ((nwritten = write(fd_dst, buf, nread)) != nread) {
122     + warning(_("write"));
123     + if (post) {
124     + ret = 33;
125     + goto nocleanup;
126     + } else
127     + goto cleanup_0;
128     + }
129     + }
130     + }
131     +
132     + if (fd_dst != -1)
133     + close(fd_dst);
134     + if (fd_src != -1)
135     + close(fd_src);
136     + fd_dst = fd_src = -1;
137     + }
138     +
139     + ret = 0;
140     + /* remove temporary files (post=1) */
141     + for (n = 0; n < argc - 1; n += 2)
142     + unlink(argv[n]);
143     +nocleanup:
144     + if (fd_dst != -1)
145     + close(fd_dst);
146     + if (fd_src != -1)
147     + close(fd_src);
148     + _exit(ret);
149     +cleanup_0:
150     + /* remove temporary files (post=0) */
151     + for (n = 0; n < argc - 1; n += 2)
152     + unlink(argv[n+1]);
153     + if (fd_dst != -1)
154     + close(fd_dst);
155     + if (fd_src != -1)
156     + close(fd_src);
157     + _exit(32);
158     + } else {
159     +
160     + /* Shift argv and make a copy of the command to execute. */
161     + argv++;
162     + argc--;
163     + cmnd = estrdup(argv[0]);
164     +
165     + /* If invoked as a login shell, modify argv[0] accordingly. */
166     + if (argv[-1][0] == '-') {
167     + if ((cp = strrchr(argv[0], '/')) == NULL)
168     + cp = argv[0];
169     + *cp = '-';
170     + }
171     + sudo_execve(cmnd, argv, envp, noexec);
172     + warning(_("unable to execute %s"), argv[0]);
173     + sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, EXIT_FAILURE);
174     }
175     - sudo_execve(cmnd, argv, envp, noexec);
176     - warning(_("unable to execute %s"), argv[0]);
177     - sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, EXIT_FAILURE);
178     _exit(EXIT_FAILURE);
179     }
180     diff -up sudo-1.8.6p3/src/sudo.c.sudoedit-selinux sudo-1.8.6p3/src/sudo.c
181     --- sudo-1.8.6p3/src/sudo.c.sudoedit-selinux 2012-09-18 15:57:43.000000000 +0200
182     +++ sudo-1.8.6p3/src/sudo.c 2012-09-25 16:04:36.687422997 +0200
183     @@ -915,6 +915,10 @@ exec_setup(struct command_details *detai
184     if (selinux_setup(details->selinux_role, details->selinux_type,
185     ptyname ? ptyname : user_details.tty, ptyfd) == -1)
186     goto done;
187     + if (details->flags & CD_SUDOEDIT_COPY) {
188     + rval = true;
189     + goto done;
190     + }
191     }
192     #endif
193    
194     @@ -1116,6 +1120,8 @@ run_command(struct command_details *deta
195     break;
196     case CMD_WSTATUS:
197     /* Command ran, exited or was killed. */
198     + if (details->flags & CD_SUDOEDIT_COPY)
199     + break;
200     sudo_debug_printf(SUDO_DEBUG_DEBUG,
201     "calling policy close with wait status %d", cstat.val);
202     policy_close(&policy_plugin, cstat.val, 0);
203     diff -up sudo-1.8.6p3/src/sudo_edit.c.sudoedit-selinux sudo-1.8.6p3/src/sudo_edit.c
204     --- sudo-1.8.6p3/src/sudo_edit.c.sudoedit-selinux 2012-09-18 15:56:30.000000000 +0200
205     +++ sudo-1.8.6p3/src/sudo_edit.c 2012-09-25 16:06:19.108564255 +0200
206     @@ -49,11 +49,284 @@
207     #if TIME_WITH_SYS_TIME
208     # include <time.h>
209     #endif
210     +#ifdef HAVE_SELINUX
211     +# include <selinux/selinux.h>
212     +#endif
213    
214     #include "sudo.h"
215    
216     #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
217    
218     +struct tempfile {
219     + char *tfile;
220     + char *ofile;
221     + struct timeval omtim;
222     + off_t osize;
223     +};
224     +
225     +static int
226     +selinux_edit_copy(struct command_details *command_details, struct tempfile *tf, char **files, int nfiles, const char *tmpdir, int tmplen, int tval_isset)
227     +{
228     + char **sesh_args;
229     + int i, sesh_nargs, ret;
230     + struct command_details sesh_details;
231     + debug_decl(selinux_edit_copy, SUDO_DEBUG_EDIT);
232     +
233     + /* Prepare selinux stuff (setexeccon) */
234     + if (selinux_setup(command_details->selinux_role,
235     + command_details->selinux_type, NULL, -1) != 0)
236     + return -1;
237     +
238     + if (nfiles < 1)
239     + return 1;
240     +
241     + /* Construct common args for sesh */
242     + memcpy(&sesh_details, command_details, sizeof(sesh_details));
243     + sesh_details.command = _PATH_SUDO_SESH;
244     + sesh_details.flags |= CD_SUDOEDIT_COPY;
245     +
246     + sesh_nargs = (nfiles * 2) + 4 + 1;
247     + sesh_args = (char **)emalloc2(sesh_nargs, sizeof(char *));
248     + sesh_args++;
249     + sesh_args[0] = "sesh";
250     + sesh_args[1] = "-e";
251     +
252     + if (files != NULL) {
253     + sesh_args[2] = "0";
254     +
255     + for (i = 2; i < nfiles+2; ++i) {
256     + sesh_args[2*i-1] = files[i-2];
257     + tf[i-2].ofile = files[i-2];
258     + /*
259     + * O_CREAT | O_EXCL is used in the sesh helper, so the
260     + * usage of the tempnam function here is safe.
261     + */
262     + sesh_args[2*i] = tempnam(tmpdir, "sudo.");
263     + tf[i-2].tfile = sesh_args[2*i];
264     + //tf[i-2].omtim = 0;
265     + tf[i-2].osize = 0;
266     + }
267     +
268     + sesh_args[2*i-1] = NULL;
269     +
270     + /* Run sesh -e 0 <o1> <t1> ... <on> <tn> */
271     + sesh_details.argv = sesh_args;
272     + switch(run_command(&sesh_details)) {
273     + case 0:
274     + break;
275     + case 31:
276     + error(1, _("sesh: internal error: odd number of paths"));
277     + case 32:
278     + error(1, _("sesh: unable to create temporary files"));
279     + }
280     +
281     + /* Chown to user's UID so he can edit the temporary files */
282     + for (i = 2; i < nfiles+2; ++i) {
283     + if (chown(tf[i-2].tfile, user_details.uid, user_details.gid) != 0) {
284     + warning("Unable to chown(%s) to %d:%d for editing",
285     + tf[i-2].tfile, user_details.uid, user_details.gid);
286     + }
287     + }
288     + } else {
289     + sesh_args[2] = "1";
290     +
291     + /* Construct args for sesh -e 1 */
292     + for (i = 2; i < nfiles+2; ++i) {
293     + sesh_args[2*i-1] = tf[i-2].tfile;
294     + sesh_args[2*i] = tf[i-2].ofile;
295     +
296     + if (chown(tf[i-2].tfile, sesh_details.uid, sesh_details.gid) != 0) {
297     + warning("Unable to chown(%s) back to %d:%d",
298     + tf[i-2].tfile, sesh_details.uid, sesh_details.gid);
299     + }
300     + }
301     +
302     + sesh_args[2*i-1] = NULL;
303     +
304     + /* Run sesh -e 1 <t1> <o1> ... <tn> <on> */
305     + sesh_details.argv = sesh_args;
306     + switch(run_command(&sesh_details)) {
307     + case 0:
308     + break;
309     + case 32:
310     + warning(_("Copying the temporary files back to its original place failed. The files were left in %s"), tmpdir);
311     + break;
312     + case 33:
313     + warning(_("Copying of some of the temporary files back to its original place failed and they were left in %s"),
314     + tmpdir);
315     + break;
316     + }
317     + }
318     +
319     + return (nfiles);
320     +}
321     +
322     +static void switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups);
323     +
324     +static int sudo_edit_copy(struct command_details *command_details, struct tempfile *tf, char **files, int nfiles, const char *tmpdir, int tmplen, int tval_isset)
325     +{
326     + int i, j, tfd, ofd, rc;
327     + char *cp, *suff, buf[BUFSIZ];
328     + ssize_t nwritten, nread;
329     + struct stat sb;
330     + struct timeval tv;
331     + debug_decl(sudo_edit_copy, SUDO_DEBUG_EDIT);
332     +
333     + if (files != NULL) {
334     + /* Create temporary copies */
335     + for (i = 0, j = 0; i < nfiles; i++) {
336     + rc = -1;
337     + switch_user(command_details->euid, command_details->egid,
338     + command_details->ngroups, command_details->groups);
339     + if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) {
340     + if (ofd == -1) {
341     + zero_bytes(&sb, sizeof(sb)); /* new file */
342     + rc = 0;
343     + } else {
344     + rc = fstat(ofd, &sb);
345     + }
346     + }
347     + switch_user(ROOT_UID, user_details.egid,
348     + user_details.ngroups, user_details.groups);
349     + if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) {
350     + if (rc)
351     + warning("%s", files[i]);
352     + else
353     + warningx(_("%s: not a regular file"), files[i]);
354     + if (ofd != -1)
355     + close(ofd);
356     + continue;
357     + }
358     + tf[j].ofile = files[i];
359     + tf[j].osize = sb.st_size;
360     + mtim_get(&sb, &tf[j].omtim);
361     + if ((cp = strrchr(tf[j].ofile, '/')) != NULL)
362     + cp++;
363     + else
364     + cp = tf[j].ofile;
365     + suff = strrchr(cp, '.');
366     + if (suff != NULL) {
367     + easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir,
368     + (int)(size_t)(suff - cp), cp, suff);
369     + } else {
370     + easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp);
371     + }
372     + if (seteuid(user_details.uid) != 0)
373     + error(1, "seteuid(%d)", (int)user_details.uid);
374     + tfd = mkstemps(tf[j].tfile, suff ? strlen(suff) : 0);
375     + if (seteuid(ROOT_UID) != 0)
376     + error(1, "seteuid(ROOT_UID)");
377     + if (tfd == -1) {
378     + warning("mkstemps");
379     + goto cleanup;
380     + }
381     + if (ofd != -1) {
382     + while ((nread = read(ofd, buf, sizeof(buf))) != 0) {
383     + if ((nwritten = write(tfd, buf, nread)) != nread) {
384     + if (nwritten == -1)
385     + warning("%s", tf[j].tfile);
386     + else
387     + warningx(_("%s: short write"), tf[j].tfile);
388     + goto cleanup;
389     + }
390     + }
391     + close(ofd);
392     + }
393     + /*
394     + * We always update the stashed mtime because the time
395     + * resolution of the filesystem the temporary file is on may
396     + * not match that of the filesystem where the file to be edited
397     + * resides. It is OK if touch() fails since we only use the info
398     + * to determine whether or not a file has been modified.
399     + */
400     + (void) touch(tfd, NULL, &tf[j].omtim);
401     + rc = fstat(tfd, &sb);
402     + if (!rc)
403     + mtim_get(&sb, &tf[j].omtim);
404     + close(tfd);
405     + j++;
406     + }
407     + if ((nfiles = j) == 0)
408     + goto cleanup; /* no files readable, you lose */
409     + } else {
410     + /* Copy contents of temp files to real ones */
411     + for (i = 0; i < nfiles; i++) {
412     + rc = -1;
413     + if (seteuid(user_details.uid) != 0)
414     + error(1, "seteuid(%d)", (int)user_details.uid);
415     + if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) {
416     + rc = fstat(tfd, &sb);
417     + }
418     + if (seteuid(ROOT_UID) != 0)
419     + error(1, "seteuid(ROOT_UID)");
420     + if (rc || !S_ISREG(sb.st_mode)) {
421     + if (rc)
422     + warning("%s", tf[i].tfile);
423     + else
424     + warningx(_("%s: not a regular file"), tf[i].tfile);
425     + warningx(_("%s left unmodified"), tf[i].ofile);
426     + if (tfd != -1)
427     + close(tfd);
428     + continue;
429     + }
430     + mtim_get(&sb, &tv);
431     + if (tf[i].osize == sb.st_size && timevalcmp(&tf[i].omtim, &tv, ==)) {
432     + /*
433     + * If mtime and size match but the user spent no measurable
434     + * time in the editor we can't tell if the file was changed.
435     + */
436     + if (tval_isset) {
437     + warningx(_("%s unchanged"), tf[i].ofile);
438     + unlink(tf[i].tfile);
439     + close(tfd);
440     + continue;
441     + }
442     + }
443     + switch_user(command_details->euid, command_details->egid,
444     + command_details->ngroups, command_details->groups);
445     + ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644);
446     + switch_user(ROOT_UID, user_details.egid,
447     + user_details.ngroups, user_details.groups);
448     + if (ofd == -1) {
449     + warning(_("unable to write to %s"), tf[i].ofile);
450     + warningx(_("contents of edit session left in %s"), tf[i].tfile);
451     + close(tfd);
452     + continue;
453     + }
454     + while ((nread = read(tfd, buf, sizeof(buf))) > 0) {
455     + if ((nwritten = write(ofd, buf, nread)) != nread) {
456     + if (nwritten == -1)
457     + warning("%s", tf[i].ofile);
458     + else
459     + warningx(_("%s: short write"), tf[i].ofile);
460     + break;
461     + }
462     + }
463     + if (nread == 0) {
464     + /* success, got EOF */
465     + unlink(tf[i].tfile);
466     + } else if (nread < 0) {
467     + warning(_("unable to read temporary file"));
468     + warningx(_("contents of edit session left in %s"), tf[i].tfile);
469     + } else {
470     + warning(_("unable to write to %s"), tf[i].ofile);
471     + warningx(_("contents of edit session left in %s"), tf[i].tfile);
472     + }
473     + close(ofd);
474     + }
475     + j = 0;
476     + }
477     +
478     + debug_return_int(j);
479     +cleanup:
480     + for (i = 0; i < nfiles; i++) {
481     + if (tf[i].tfile != NULL)
482     + unlink(tf[i].tfile);
483     + }
484     +
485     + debug_return_int(-1);
486     +}
487     +
488     static void
489     switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
490     {
491     @@ -87,20 +360,17 @@ int
492     sudo_edit(struct command_details *command_details)
493     {
494     struct command_details editor_details;
495     - ssize_t nread, nwritten;
496     const char *tmpdir;
497     - char *cp, *suff, **nargv, **ap, **files = NULL;
498     - char buf[BUFSIZ];
499     - int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen;
500     - int editor_argc = 0, nfiles = 0;
501     + char **ap;
502     + char **nargv, **files = NULL;
503     + int editor_argc = 0;
504     + int i, ac, nargc, rval, nfiles = 0, tmplen;
505     struct stat sb;
506     - struct timeval tv, tv1, tv2;
507     - struct tempfile {
508     - char *tfile;
509     - char *ofile;
510     - struct timeval omtim;
511     - off_t osize;
512     - } *tf = NULL;
513     + struct timeval tv1, tv2;
514     + struct tempfile *tf;
515     +#ifdef HAVE_SELINUX
516     + int rbac_enabled;
517     +#endif
518     debug_decl(sudo_edit, SUDO_DEBUG_EDIT)
519    
520     /*
521     @@ -109,7 +379,7 @@ sudo_edit(struct command_details *comman
522     */
523     if (setuid(ROOT_UID) != 0) {
524     warning(_("unable to change uid to root (%u)"), ROOT_UID);
525     - goto cleanup;
526     + return 1;
527     }
528    
529     /*
530     @@ -127,6 +397,9 @@ sudo_edit(struct command_details *comman
531     while (tmplen > 0 && tmpdir[tmplen - 1] == '/')
532     tmplen--;
533    
534     +#ifdef HAVE_SELINUX
535     + rbac_enabled = is_selinux_enabled() > 0 && command_details->selinux_role != NULL;
536     +#endif
537     /*
538     * The user's editor must be separated from the files to be
539     * edited by a "--" option.
540     @@ -141,7 +414,7 @@ sudo_edit(struct command_details *comman
541     }
542     if (nfiles == 0) {
543     warningx(_("plugin error: missing file list for sudoedit"));
544     - goto cleanup;
545     + return 1;
546     }
547    
548     /*
549     @@ -150,81 +423,18 @@ sudo_edit(struct command_details *comman
550     */
551     tf = emalloc2(nfiles, sizeof(*tf));
552     zero_bytes(tf, nfiles * sizeof(*tf));
553     - for (i = 0, j = 0; i < nfiles; i++) {
554     - rc = -1;
555     - switch_user(command_details->euid, command_details->egid,
556     - command_details->ngroups, command_details->groups);
557     - if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) {
558     - if (ofd == -1) {
559     - zero_bytes(&sb, sizeof(sb)); /* new file */
560     - rc = 0;
561     - } else {
562     - rc = fstat(ofd, &sb);
563     - }
564     - }
565     - switch_user(ROOT_UID, user_details.egid,
566     - user_details.ngroups, user_details.groups);
567     - if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) {
568     - if (rc)
569     - warning("%s", files[i]);
570     - else
571     - warningx(_("%s: not a regular file"), files[i]);
572     - if (ofd != -1)
573     - close(ofd);
574     - continue;
575     - }
576     - tf[j].ofile = files[i];
577     - tf[j].osize = sb.st_size;
578     - mtim_get(&sb, &tf[j].omtim);
579     - if ((cp = strrchr(tf[j].ofile, '/')) != NULL)
580     - cp++;
581     - else
582     - cp = tf[j].ofile;
583     - suff = strrchr(cp, '.');
584     - if (suff != NULL) {
585     - easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir,
586     - (int)(size_t)(suff - cp), cp, suff);
587     - } else {
588     - easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp);
589     - }
590     - if (seteuid(user_details.uid) != 0)
591     - error(1, "seteuid(%d)", (int)user_details.uid);
592     - tfd = mkstemps(tf[j].tfile, suff ? strlen(suff) : 0);
593     - if (seteuid(ROOT_UID) != 0)
594     - error(1, "seteuid(ROOT_UID)");
595     - if (tfd == -1) {
596     - warning("mkstemps");
597     - goto cleanup;
598     - }
599     - if (ofd != -1) {
600     - while ((nread = read(ofd, buf, sizeof(buf))) != 0) {
601     - if ((nwritten = write(tfd, buf, nread)) != nread) {
602     - if (nwritten == -1)
603     - warning("%s", tf[j].tfile);
604     - else
605     - warningx(_("%s: short write"), tf[j].tfile);
606     - goto cleanup;
607     - }
608     - }
609     - close(ofd);
610     - }
611     - /*
612     - * We always update the stashed mtime because the time
613     - * resolution of the filesystem the temporary file is on may
614     - * not match that of the filesystem where the file to be edited
615     - * resides. It is OK if touch() fails since we only use the info
616     - * to determine whether or not a file has been modified.
617     - */
618     - (void) touch(tfd, NULL, &tf[j].omtim);
619     - rc = fstat(tfd, &sb);
620     - if (!rc)
621     - mtim_get(&sb, &tf[j].omtim);
622     - close(tfd);
623     - j++;
624     - }
625     - if ((nfiles = j) == 0)
626     - goto cleanup; /* no files readable, you lose */
627     +
628     + /* Make temporary copies of the original files */
629     + if (!rbac_enabled)
630     + nfiles = sudo_edit_copy(command_details, tf, files, nfiles, tmpdir, tmplen, 0);
631     + else
632     + nfiles = selinux_edit_copy(command_details, tf, files, nfiles, tmpdir, tmplen, 0);
633    
634     + if (nfiles <= 0)
635     + return 1;
636     +
637     + switch_user(ROOT_UID, user_details.egid,
638     + user_details.ngroups, user_details.groups);
639     /*
640     * Allocate space for the new argument vector and fill it in.
641     * We concatenate the editor with its args and the file list
642     @@ -253,84 +463,18 @@ sudo_edit(struct command_details *comman
643     editor_details.argv = nargv;
644     rval = run_command(&editor_details);
645     gettimeofday(&tv2, NULL);
646     + timevalsub(&tv1, &tv2);
647    
648     - /* Copy contents of temp files to real ones */
649     - for (i = 0; i < nfiles; i++) {
650     - rc = -1;
651     - if (seteuid(user_details.uid) != 0)
652     - error(1, "seteuid(%d)", (int)user_details.uid);
653     - if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) {
654     - rc = fstat(tfd, &sb);
655     - }
656     - if (seteuid(ROOT_UID) != 0)
657     - error(1, "seteuid(ROOT_UID)");
658     - if (rc || !S_ISREG(sb.st_mode)) {
659     - if (rc)
660     - warning("%s", tf[i].tfile);
661     - else
662     - warningx(_("%s: not a regular file"), tf[i].tfile);
663     - warningx(_("%s left unmodified"), tf[i].ofile);
664     - if (tfd != -1)
665     - close(tfd);
666     - continue;
667     - }
668     - mtim_get(&sb, &tv);
669     - if (tf[i].osize == sb.st_size && timevalcmp(&tf[i].omtim, &tv, ==)) {
670     - /*
671     - * If mtime and size match but the user spent no measurable
672     - * time in the editor we can't tell if the file was changed.
673     - */
674     - timevalsub(&tv1, &tv2);
675     - if (timevalisset(&tv2)) {
676     - warningx(_("%s unchanged"), tf[i].ofile);
677     - unlink(tf[i].tfile);
678     - close(tfd);
679     - continue;
680     - }
681     - }
682     - switch_user(command_details->euid, command_details->egid,
683     - command_details->ngroups, command_details->groups);
684     - ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644);
685     - switch_user(ROOT_UID, user_details.egid,
686     - user_details.ngroups, user_details.groups);
687     - if (ofd == -1) {
688     - warning(_("unable to write to %s"), tf[i].ofile);
689     - warningx(_("contents of edit session left in %s"), tf[i].tfile);
690     - close(tfd);
691     - continue;
692     - }
693     - while ((nread = read(tfd, buf, sizeof(buf))) > 0) {
694     - if ((nwritten = write(ofd, buf, nread)) != nread) {
695     - if (nwritten == -1)
696     - warning("%s", tf[i].ofile);
697     - else
698     - warningx(_("%s: short write"), tf[i].ofile);
699     - break;
700     - }
701     - }
702     - if (nread == 0) {
703     - /* success, got EOF */
704     - unlink(tf[i].tfile);
705     - } else if (nread < 0) {
706     - warning(_("unable to read temporary file"));
707     - warningx(_("contents of edit session left in %s"), tf[i].tfile);
708     - } else {
709     - warning(_("unable to write to %s"), tf[i].ofile);
710     - warningx(_("contents of edit session left in %s"), tf[i].tfile);
711     - }
712     - close(ofd);
713     - }
714     + switch_user(ROOT_UID, user_details.egid,
715     + user_details.ngroups, user_details.groups);
716     +
717     + /* Copy the temporary files back to originals */
718     + if (!rbac_enabled)
719     + nfiles = sudo_edit_copy(command_details, tf, NULL, nfiles, NULL, 0, timevalisset(&tv2));
720     + else
721     + nfiles = selinux_edit_copy(command_details, tf, NULL, nfiles, NULL, 0, timevalisset(&tv2));
722     +
723     debug_return_int(rval);
724     -
725     -cleanup:
726     - /* Clean up temp files and return. */
727     - if (tf != NULL) {
728     - for (i = 0; i < nfiles; i++) {
729     - if (tf[i].tfile != NULL)
730     - unlink(tf[i].tfile);
731     - }
732     - }
733     - debug_return_int(1);
734     }
735    
736     #else /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
737     diff -up sudo-1.8.6p3/src/sudo.h.sudoedit-selinux sudo-1.8.6p3/src/sudo.h
738     --- sudo-1.8.6p3/src/sudo.h.sudoedit-selinux 2012-09-18 15:56:30.000000000 +0200
739     +++ sudo-1.8.6p3/src/sudo.h 2012-09-25 16:04:36.690423001 +0200
740     @@ -130,6 +130,7 @@ struct user_details {
741     #define CD_RBAC_ENABLED 0x0800
742     #define CD_USE_PTY 0x1000
743     #define CD_SET_UTMP 0x2000
744     +#define CD_SUDOEDIT_COPY 0x4000
745    
746     struct command_details {
747     uid_t uid;

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed