Dave,

This patch fixes the problem for me, using Frank's test program.

The failure Frank was having is due to lis_fattach() having to
call sys_mount() (indirectly) which in turn eventually calls
do_add_mount() (in the kernel, file fs/namespace.c).  do_add_mount()
unconditionally tests capable(CAP_SYS_ADMIN), which fails if the
process context is not running as effectively as root (as set from
the user level via seteuid) and returns EPERM.

I offer the attached patch, Dave, only to demonstrate a potential
fix for Frank's problem, for Frank to try and for you to do with
as you see fit.  It's against 2.16.13.

It sets CAP_SYS_ADMIN inside the lis_mount() and lis_umount2()
routines, which are syscall wrappers for sys_mount() and sys_umount2().

For simplicity, it wraps the kernel capability stuff in FATTACH_VIA_MOUNT; which may or may not be appropriate, but I only
have 2.4.22 here right now, so I have no idea when this stuff was
added or how it has changed.


-John

David Grothe wrote:
I'm not an fattach specialist, so maybe someone else can answer this.
-- Dave

Subject: fattach failed on application without super user privilege
To: [EMAIL PROTECTED]
From: [EMAIL PROTECTED]
Date: Thu, 25 Sep 2003 09:59:18 -0400


Hi,
I have an application running with LiS-2.16/Linux 2.4.18. The application
create named pipe, and push connld, and attach it (the program showed in
belows). It always failed on the calling fattach fucntion if the
application does not have super-user privilege. I tried fattach utility and
got the same result ("Operation is not permitted"). If the application run
on the super user mode, it succeeded. I need my application run on
non-super user mode, how can I do it ? Thanks



#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <memory.h> #include <fcntl.h> #include <errno.h> #include <limits.h> #include <stropts.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/sysmacros.h> #include <sys/ioctl.h>


int main( int argc, char *argv[] ) { int fd[2];

      if (pipe(fd) < 0)  {
            fprintf( stderr,
                  "pipe() failed: %s\n", strerror(errno) );
            exit(1);
      }
      fcntl(fd[1], F_SETFL, O_NONBLOCK);
      mknod("pipe1", S_IFIFO | 0666, 0);

      if (ioctl( fd[1], I_PUSH, "connld" ) < 0) {
            fprintf( stderr,
                  "ioctl( %d, I_PUSH, connld ) failed: %s\n",
                  fd[1], strerror(errno) );
            exit(1);
      }

      if (fattach( fd[1], "pipe1" ) < 0) {
            fprintf( stderr, "fattach( %d, \"pipe1\" ) failed: %d %s\n",
                  fd[1], errno, strerror(errno) );
            exit(1);
      }

      close(fd[0]);
      close(fd[1]);

      exit(0);
}



Frank Chi
Senior Programming Engineer
Ingenico Atlanta
(678) 795-2850 Direct
(770) 594-6003 Fax



_______________________________________________ Linux-streams mailing list [EMAIL PROTECTED] http://gsyc.escet.urjc.es/mailman/listinfo/linux-streams


--- LiS-2.16.13-orig/head/linux-mdep.c  2003-07-15 15:58:21.000000000 -0400
+++ LiS-2.16.13/head/linux-mdep.c       2003-09-25 20:58:00.000000000 -0400
@@ -77,6 +77,9 @@
 #include <linux/pipe_fs_i.h>
 #ifdef KERNEL_2_3
 #include <linux/mount.h>
+#if defined(FATTACH_VIA_MOUNT)
+#include <linux/capability.h>
+#endif
 #endif
 #include <linux/time.h>
 
@@ -4446,12 +4449,23 @@
 {
     mm_segment_t       old_fs;
     int                        ret;
+#if defined(FATTACH_VIA_MOUNT)
+    kernel_cap_t        cap = current->cap_effective;
+#endif
 
     old_fs = get_fs();
     set_fs(KERNEL_DS);
 
+#if defined(FATTACH_VIA_MOUNT)
+    cap_raise(current->cap_effective, CAP_SYS_ADMIN);
+#endif
+
     ret = syscall_mount(dev_name, dir_name, fstype, rwflag, data) ;
 
+#if defined(FATTACH_VIA_MOUNT)
+    current->cap_effective = cap;
+#endif
+
     set_fs(old_fs);
 
     return(ret < 0 ? -errno : ret) ;
@@ -4471,12 +4485,23 @@
 {
     mm_segment_t       old_fs;
     int                        ret;
+#if defined(FATTACH_VIA_MOUNT)
+    kernel_cap_t        cap = current->cap_effective;
+#endif
 
     old_fs = get_fs();
     set_fs(KERNEL_DS);
 
+#if defined(FATTACH_VIA_MOUNT)
+    cap_raise(current->cap_effective, CAP_SYS_ADMIN);
+#endif
+
     ret = syscall_umount2(path, flags) ;
 
+#if defined(FATTACH_VIA_MOUNT)
+    current->cap_effective = cap;
+#endif
+
     set_fs(old_fs);
 
     return(ret < 0 ? -errno : ret) ;

Reply via email to