[linux-cifs-client] Re: cifs vfs 0.9.9a for 2.4 released to web site

Lin Li linl at xandros.com
Fri Dec 12 14:55:17 GMT 2003


Steve French wrote:

>I updated the web site to reflect the current 2.4 version of the cifs
>vfs (0.9.9a) and if continued testing by the community goes reasonably
>well will announce to freshmeat etc.
>
>I also updated the mount helper in cvs and the one on the web site to
>include the fix to allow mount suid but solving the user unmount problem
>is harder.  I would like to use the /proc/mounts entry for the
>mountpoint to be unmounted and look for a string like "mntuid=xx" as a
>way of letting (the new) umount.cifs utility be able to check the
>current uid vs. that of the user who mounted to that mount point. 
>umount.cifs would be optional of course - just for those who want to be
>able to suid umount what they mounted.   I am not a big fan of ioctls
>but if the approach to using /proc/mounts is a bad idea, I will probably
>have to fall back to adding an ioctl for this.  
>
>A more pressing problem I would like to solve (suggestions would be VERY
>welcome) is how to pass the mount return code back from the kernel on
>failed mounts in 2.4 - it seems that my mount return code gets
>overwritten by the kernel on the way out - I may be able to overwrite
>the data area passed into with an "rc=xxx" text string - but I think
>that that buffer is a dummy buffer too (not sure) so that might not do
>any good either - that may be a case where an ioctl makes sense but it
>looks odd (fortunately would only apply to 2.4) to use an ioctl to
>retrieve "last mount return code" but the only other obvious alternative
>is to put it in /proc/fs/cifs/<pid> but that looks even worse
>
>  
>
Does the new version solve the symbolic link problem? It's a serious bug.

As the mount helper, there is more improvement needs to be done. I did 
some changes here:
---------------------------------------------------------------------------------------------
--- mount.cifs.c        8 Dec 2003 16:02:55 -0000       1.4
+++ mount.cifs.c        11 Dec 2003 18:43:16 -0000      1.6
@@ -289,6 +289,37 @@
        }
 }

+/* Make a canonical pathname from PATH.  Returns a freshly malloced string.
+   It is up the *caller* to ensure that the PATH is sensible.  i.e.
+   canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though 
``/dev/fd0/.''
+   is not a legal pathname for ``/dev/fd0''  Anything we cannot parse
+   we return unmodified.   */
+static char *
+canonicalize (char *path)
+{
+       char *canonical = malloc (PATH_MAX + 1);
+
+       if (!canonical) {
+               printf("Error! Not enough memory!\n");
+               return NULL;
+       }
+
+       if (strlen(path) > PATH_MAX) {
+               printf("Mount point string too long\n");
+               return NULL;
+       }
+
+       if (path == NULL)
+               return NULL;
+
+       if (realpath (path, canonical))
+               return canonical;
+
+       strncpy (canonical, path, PATH_MAX);
+       canonical[PATH_MAX] = '\0';
+       return canonical;
+}
+
 static struct option longopts[] = {
        { "all", 0, 0, 'a' },
        { "help", 0, 0, 'h' },
@@ -330,6 +361,7 @@
        char * mountpoint;
        char * options;
        char * temp;
+       char *p;
        int rc,i;
        int rsize = 0;
        int wsize = 0;
@@ -360,7 +392,7 @@
        if(argc < 3)
                mount_cifs_usage();
        share_name = argv[1];
-       mountpoint = argv[2];
+       mountpoint = canonicalize(argv[2]);
        /* add sharename in opts string as unc= parm */

        while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
@@ -503,6 +535,25 @@
                return 1; */
        if (orgoptions && parse_options(strdup(orgoptions)))
                return 1;
+
+       if (got_user == 0 && getenv("USER")) {
+               user_name = malloc(256);
+               if (user_name)
+               {
+                       strncpy(user_name, getenv("USER"), 255);
+                       got_user = 1;
+
+                       if ((p=strchr(user_name,'%'))) {
+                               *p = 0;
+                               mountpassword = malloc(33);
+                               if (mountpassword) {
+                                       strncpy(mountpassword, p+1,32);
+                                       got_password = 1;
+                                       
memset(p+1,'\0',strlen(mountpassword));
+                               }
+                       }
+               }
+       }

        if(got_user == 0)
                user_name = getusername();
----------------------------------------------------------------------------------

As for umount, the /proc/mounts does not has a "mounted_uid=xx" recorded 
(I'm using 0.8.7a, don't know if it's changed in 0.9.9a). Here is a util 
I written. Let me know if there is anything wrong.
-------------------------------------------------------------------
/*
 *  cifsumount.c
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <mntent.h>
#include <sys/types.h>
#include <sys/stat.h>

static void
usage(void)
{
        printf("usage: cifsumount mountpoint\n");
}

static int
umount_ok(const char *mount_point)
{
        int mounted = 0;
        FILE* mtab;
        struct mntent *mnt;
        struct stat st;

        if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
                fprintf(stderr, "Can't open " MOUNTED ": %s\n",
                        strerror(errno));
                return 1;
        }

        while ((mnt = getmntent(mtab)) != NULL) {
                if (strcmp(mnt->mnt_type, "cifs") == 0 && 
strcmp(mnt->mnt_dir, mount_point) == 0) {
                        mounted = 1;
                        break;
                }
        }

        endmntent(mtab);

        if (!mounted) {
                fprintf(stderr, "%s probably not cifs-filesystem\n",
                        mount_point);
                return -1;
        }

        if (stat(mount_point, &st) == -1) {
                fprintf(stderr, "Could not open %s: %s\n",
                        mount_point, strerror(errno));
                return -1;
        }

        if ((getuid() != 0)
            && (st.st_uid != getuid())) {
                fprintf(stderr, "You are not allowed to umount %s\n",
                        mount_point);
                return -1;
        }

        return 0;
}

/* Make a canonical pathname from PATH.  Returns a freshly malloced string.
   It is up the *caller* to ensure that the PATH is sensible.  i.e.
   canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
   is not a legal pathname for ``/dev/fd0''  Anything we cannot parse
   we return unmodified.   */
static char *
canonicalize (char *path)
{
        char *canonical = malloc (PATH_MAX + 1);

        if (!canonical) {
                fprintf(stderr, "Error! Not enough memory!\n");
                return NULL;
        }

        if (strlen(path) > PATH_MAX) {
                fprintf(stderr, "Mount point string too long\n");
                return NULL;
        }

        if (path == NULL)
                return NULL;

        if (realpath (path, canonical))
                return canonical;

        strncpy (canonical, path, PATH_MAX);
        canonical[PATH_MAX] = '\0';
        return canonical;
}

int
main(int argc, char *argv[])
{
        int fd;
        char* mount_point;
        struct mntent *mnt;
        FILE* mtab;
        FILE* new_mtab;

        if (argc != 2) {
                usage();
                exit(1);
        }

        if (geteuid() != 0) {
                fprintf(stderr, "cifsumount must be installed suid root\n");
                exit(1);
        }

        mount_point = canonicalize(argv[1]);

        if (mount_point == NULL)
        {
                exit(1);
        }

        if (umount_ok(mount_point) != 0) {
                exit(1);
        }

        if (umount(mount_point) != 0) {
                fprintf(stderr, "Could not umount %s: %s\n",
                        mount_point, strerror(errno));
                exit(1);
        }

        if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
        {
                fprintf(stderr, "Can't get "MOUNTED"~ lock file");
                return 1;
        }
        close(fd);

        if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
                fprintf(stderr, "Can't open " MOUNTED ": %s\n",
                        strerror(errno));
                return 1;
        }

#define MOUNTED_TMP MOUNTED".tmp"

        if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
                fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n",
                        strerror(errno));
                endmntent(mtab);
                return 1;
        }

        while ((mnt = getmntent(mtab)) != NULL) {
                if (strcmp(mnt->mnt_dir, mount_point) != 0) {
                        addmntent(new_mtab, mnt);
                }
        }

        endmntent(mtab);

        if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 
< 0) {
                fprintf(stderr, "Error changing mode of %s: %s\n",
                        MOUNTED_TMP, strerror(errno));
                exit(1);
        }

        endmntent(new_mtab);

        if (rename(MOUNTED_TMP, MOUNTED) < 0) {
                fprintf(stderr, "Cannot rename %s to %s: %s\n",
                        MOUNTED, MOUNTED_TMP, strerror(errno));
                exit(1);
        }

        if (unlink(MOUNTED"~") == -1)
        {
                fprintf(stderr, "Can't remove "MOUNTED"~");
                return 1;
        }

        return 0;
}
------------------------------------------------------


Thanks,
Lin

-- 
Xandros Corporation
Simple. Powerful. Linux.
Visit us at http://www.xandros.com




More information about the linux-cifs-client mailing list