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

Contents 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 - (show annotations) (download)
Thu Feb 4 19:44:42 2021 UTC (3 years, 3 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 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