Login
Immutable PageDiscussionInfoAttachments
ytoku/daily-record/2011-11-22

MMA

jexecした環境でsudoが動かない件

jexecした環境でsudoを実行しようとすると

sudo: no tty present and no askpass program specified

と言われる件。

nest上に http://www.mail-archive.com/freebsd-jail@freebsd.org/msg01584.html のパッチを当ててjexec+ttyコマンドを湧かせた。一応本来のjexecはそのまま残しておく。

diff -Naru usr.sbin/jexec/Makefile usr.sbin/jexec+tty/Makefile
--- usr.sbin/jexec/Makefile     2011-03-05 12:40:17.888811727 +0900
+++ usr.sbin/jexec+tty/Makefile 2011-11-22 19:00:35.201362880 +0900
@@ -1,6 +1,7 @@
 # $FreeBSD: src/usr.sbin/jexec/Makefile,v 1.5.2.1.6.1 2010/12/21 17:09:25 kensmith Exp $
 
-PROG=  jexec
+PROG=  jexec+tty
+SRCS=  jexec.c
 MAN=   jexec.8
 DPADD= ${LIBJAIL} ${LIBUTIL}
 LDADD= -ljail -lutil
diff -Naru usr.sbin/jexec/jexec.c usr.sbin/jexec+tty/jexec.c
--- usr.sbin/jexec/jexec.c      2011-03-05 12:40:17.890810865 +0900
+++ usr.sbin/jexec+tty/jexec.c  2011-11-22 19:01:44.961332469 +0900
@@ -37,16 +37,20 @@
 
 #include <err.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <jail.h>
 #include <limits.h>
+#include <libutil.h>
 #include <login_cap.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <termios.h>
 #include <pwd.h>
 #include <unistd.h>
 
 static void    usage(void);
+static void    newpty(void);
 
 #define GET_USER_INFO do {                                             \
        pwd = getpwnam(username);                                       \
@@ -71,17 +75,17 @@
        login_cap_t *lcap = NULL;
        struct passwd *pwd = NULL;
        gid_t *groups = NULL;
-       int ch, ngroups, uflag, Uflag;
+       int ch, ngroups, uflag, Uflag, tflag;
        long ngroups_max;
        char *username;
 
-       ch = uflag = Uflag = 0;
+       ch = uflag = Uflag = tflag = 0;
        username = NULL;
        ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
        if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
                err(1, "malloc");
 
-       while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
+       while ((ch = getopt(argc, argv, "nu:U:t")) != -1) {
                switch (ch) {
                case 'n':
                        /* Specified name, now unused */
@@ -94,6 +98,9 @@
                        username = optarg;
                        Uflag = 1;
                        break;
+               case 't':
+                       tflag = 1;
+                       break;
                default:
                        usage();
                }
@@ -125,6 +132,8 @@
                        err(1, "setusercontext");
                login_close(lcap);
        }
+       if (tflag)
+               newpty();
        if (execvp(argv[1], argv + 1) == -1)
                err(1, "execvp(): %s", argv[1]);
        exit(0);
@@ -135,6 +144,68 @@
 {
 
        fprintf(stderr, "%s\n",
-               "usage: jexec [-u username | -U username] jail command ...");
+               "usage: jexec+tty [-u username | -U username] [-t] jail command ...");
        exit(1); 
 }
+
+static void
+newpty(void)
+{
+       int master, slave, child, n, cc;
+       fd_set rfd;
+       struct termios tt, rtt;
+       struct winsize win;
+       char obuf[BUFSIZ];
+       char ibuf[BUFSIZ];
+
+       if (tcgetattr(STDIN_FILENO, &tt) == -1)
+                err(1, "tcgetattr");
+        if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1)
+                err(1, "ioctl");
+        if (openpty(&master, &slave, NULL, &tt, &win) == -1)
+                err(1, "openpty");
+        rtt = tt;
+        cfmakeraw(&rtt);
+        rtt.c_lflag &= ~ECHO;
+        tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
+
+        child = fork();
+        if (child < 0)
+                err(1, "fork");
+        if (child == 0) {
+                close(master);
+                login_tty(slave);
+                dup2(slave, STDIN_FILENO);
+                dup2(slave, STDOUT_FILENO);
+                dup2(slave, STDERR_FILENO);
+               close(slave);
+               return;
+       }
+       FD_ZERO(&rfd);
+       for (;;) {
+               FD_SET(master, &rfd);
+                FD_SET(STDIN_FILENO, &rfd);
+                n = select(master + 1, &rfd, 0, 0, NULL);
+                if (n < 0 && errno != EINTR)
+                        break;
+                if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
+                        cc = read(STDIN_FILENO, ibuf, BUFSIZ);
+                        if (cc < 0)
+                                break;
+                        if (cc == 0)
+                                write(master, ibuf, 0);
+                        if (cc > 0) {
+                                write(master, ibuf, cc);
+                        }
+                }
+                if (n > 0 && FD_ISSET(master, &rfd)) {
+                        cc = read(master, obuf, sizeof (obuf));
+                        if (cc <= 0)
+                                break;
+                        write(STDOUT_FILENO, obuf, cc);
+                }
+        }
+       tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
+       exit(0);
+}
+

ytoku/daily-record/2011-11-22 (last edited 2011-11-22 19:19:51 by ytoku)