Regarding the "cannot execute binary file" error:

As previously noted, on my (gentoo) system this is due to using the
version of su from the 'shadow' package rather than GNU su.  I've fixed
this problem and attached a patch,
  dchroot-0.11-no_gnu_su.patch
which #ifdef's out the problematic bits.  Debian (and other) users with
the GNU version of su should define the preprocessor symbol WITH_GNU_SU.

During fixing this problem, another became apparent: dchroot cannot
pass arbitrary sets of arguments to the shell because it grabs any
argument starting with a '-'.  To fix this I've implemented the
canonical '--' option to allow all subsequent arguments to pass through
to the chrooted shell.  See
  dchroot-0.11-option_fix.patch
for the fix.

Hope these are helpful,
Chris F.
--- dchroot.c.old       2005-04-30 02:09:35.000000000 +1000
+++ dchroot.c   2005-05-01 22:37:26.000000000 +1000
@@ -199,15 +199,42 @@
                return -1;
        } else if (pid == 0) {
 
-               if (!argv) {
-                       /* Will execute a shell in the new chroot. */
+    int cmdnum = 0;
+    int argc = 0;
 
-                       cmd = malloc(sizeof(char *) * 4);
+    /* estimate length of command list to su */
+               if (!argv) {
+      argc = 4;
+               } else {
+                       while (argv[argc] != NULL) {
+        argc++;
+      }
+      argc += 5;
+    }
+    cmd = malloc(sizeof(char *) * argc);
+
+    if (!cmd) {
+      dchroot_perror("malloc");
+      exit(EXIT_FAILURE);
+    }
+
+    cmd[cmdnum++] = "/bin/su";
+
+    if (opts.dir[0] == '\0') {
+      /* /bin/su, -, username, ... */
+      cmd[cmdnum++] = "-";
+    } else {
+#ifdef WITH_GNU_SU
+      /* /bin/su, -p, username, ... */
+      cmd[cmdnum++] = "-p";
+#endif
+      /* /bin/su, username, ... */
+      /* su from shadow package doesn't know about -p option. */
+    }
+    cmd[cmdnum++] = username;
 
-                       if (!cmd) {
-                               dchroot_perror("malloc");
-                               exit(EXIT_FAILURE);
-                       }
+               if (!argv) {
+                       /* Will execute a shell in the new chroot. */
 
                        if (!opts.quiet) {
                                printf("Executing shell in '%s' chroot.\n",
@@ -215,61 +242,32 @@
                                fflush(NULL);
                        }
 
-                       cmd[0] = "/bin/su";
-
-                       if (opts.dir[0] == '\0') {
-                               /* /bin/su, -, username, NULL */
-                               cmd[1] = "-";
-                       } else {
-                               /* /bin/su, -p, username, NULL */
-                               cmd[1] = "-p";
-                       }
-                       cmd[2] = username;
-                       cmd[3] = NULL;
+                       cmd[cmdnum++] = NULL;
 
                } else {
-                       /* Will execute the command in argv[] in the
+                       /* Will execute the commands in argv[] in the
                         * new chroot. 
                         */
 
-                       int argc = 0;
-                       int i = 0, j = 0;
+                       int i = 0;
+      int shcmdstart = 0;
                        
-                       while (argv[i++] != NULL) {
-                               argc++;
-                       }
-                       
-                       cmd = malloc(sizeof(char *) * (argc + 5));
-                       
-                       if (!cmd) {
-                               dchroot_perror("malloc");
-                               exit(EXIT_FAILURE);
-                       }
-               
-                       i = 0;
-                       cmd[i++] = "/bin/su";
-                       
-                       if (opts.dir[0] == '\0') {
-                               /* /bin/su - username argv[0] argv[1] ... */
-                               cmd[i++] = "-";
-                       } else {
-                               /* /bin/su -p username argv[0] argv[1] ... */
-                               cmd[i++] = "-p";
-                       }
-                       
-                       cmd[i++] = username;
-                       cmd[i++] = "--";
-
-                       while (argv[j] != NULL) {
-                               cmd[i++] = argv[j];
-                               j++;
+#ifdef WITH_GNU_SU
+      /* prevent gnu su from grabbing options inteded for the shell */
+                       cmd[cmdnum++] = "--";
+#endif
+
+      shcmdstart = cmdnum + 1;
+                       while (argv[i] != NULL) {
+                               cmd[cmdnum++] = argv[i];
+                               i++;
                        }
 
-                       cmd[i] = NULL;
+                       cmd[cmdnum] = NULL;
 
                        if (!opts.quiet) {
                                printf("(%s) ", chroot_to->name);
-                               i = 4;
+                               i = shcmdstart;
                                while (cmd[i]) {
                                        printf("%s ", cmd[i]);
                                        i++;
--- dchroot.c.mid       2005-05-01 22:49:30.000000000 +1000
+++ dchroot.c   2005-05-02 00:09:56.000000000 +1000
@@ -250,14 +250,14 @@
                         */
 
                        int i = 0;
-      int shcmdstart = 0;
+      int sh_cmd_start = 0;
                        
 #ifdef WITH_GNU_SU
       /* prevent gnu su from grabbing options inteded for the shell */
                        cmd[cmdnum++] = "--";
 #endif
 
-      shcmdstart = cmdnum + 1;
+      sh_cmd_start = cmdnum;
                        while (argv[i] != NULL) {
                                cmd[cmdnum++] = argv[i];
                                i++;
@@ -267,7 +267,7 @@
 
                        if (!opts.quiet) {
                                printf("(%s) ", chroot_to->name);
-                               i = shcmdstart;
+                               i = sh_cmd_start;
                                while (cmd[i]) {
                                        printf("%s ", cmd[i]);
                                        i++;
@@ -345,11 +345,13 @@
 
 static void usage(char *cmd)
 {
-       printf("Usage: %s [OPTION...] [COMMAND]\n", cmd);
-       printf
-           ("Execute COMMAND under a different root filesystem, " 
-            "or if no command is given\n");
-       printf("invoke a shell.\n");
+       printf("Usage:  %s [OPTION...] [[--] COMMAND]\n", cmd);
+       printf("\n");
+       printf("Execute COMMAND under a different root filesystem, "
+                                  "or if no command is given\n");
+       printf("invoke a shell.  Using -- causes all subsequent input "
+                                  "to go to the shell\n");
+  printf("in the chroot.\n");
        printf("\n");
        printf("  -a               Execute in all known chroots.\n");
        printf("  -c newroot       Execute in specified chroot.\n");
@@ -359,7 +361,6 @@
        printf("  -q               Be quiet.\n");
        printf("  -h               Print help message.\n");
        printf("  -V               Print program version.\n");
-
 }
 
 
@@ -369,9 +370,10 @@
        int rv = 0;
        char **cmd;
        int index = 1;
+  int opts_finished = 0;
        struct passwd *pwd;
 
-       while (argv[index] && argv[index][0] == '-') {
+       while (argv[index] && argv[index][0] == '-' && ! opts_finished) {
 
                if (argv[index][1] == '\0' || argv[index][2] != '\0') {
                        dchroot_printf("Unknown option '-%c%c'.\n",
@@ -394,9 +396,7 @@
                        }
                        break;
                case 'l':
-                       if ((chroots = read_chroots(CHROOTS_CONF)) == NULL) {
-                               printf("No chroots found.\n");
-                       } else {
+                       if ((chroots = read_chroots(CHROOTS_CONF)) != NULL) {
                                list_chroots(chroots);
                                printf("\n");
                        }
@@ -413,6 +413,9 @@
                        usage(argv[0]);
                        exit(EXIT_SUCCESS);
                        break;
+    case '-':
+      opts_finished = 1;
+      break;
                default:
                        dchroot_printf("Unknown option '%s'.\n",
                                       argv[index]);
@@ -425,6 +428,7 @@
                        usage(argv[0]);
                        exit(EXIT_FAILURE);
                }
+
                index++;
        }
 

Reply via email to