[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