From: Urban Widmark - Fix module unload (Angus Sawyer). - Fix the smbfs error handling if kernel_thread() should fail. - Allow high uids/gids to be used as the fake uid smbfs sets as file owner. fs/smbfs/Makefile | 2 ++ fs/smbfs/inode.c | 42 +++++++++++++++++++++++++----------------- fs/smbfs/proto.h | 5 +++-- fs/smbfs/smbiod.c | 22 +++++++++++++--------- include/linux/smb_mount.h | 10 +++++----- 5 files changed, 48 insertions(+), 33 deletions(-) diff -puN fs/smbfs/inode.c~smbfs-fixes fs/smbfs/inode.c --- 25/fs/smbfs/inode.c~smbfs-fixes 2003-09-13 11:32:36.000000000 -0700 +++ 25-akpm/fs/smbfs/inode.c 2003-09-13 11:32:36.000000000 -0700 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -447,6 +448,19 @@ smb_show_options(struct seq_file *s, str } static void +smb_unload_nls(struct smb_sb_info *server) +{ + if (server->remote_nls) { + unload_nls(server->remote_nls); + server->remote_nls = NULL; + } + if (server->local_nls) { + unload_nls(server->local_nls); + server->local_nls = NULL; + } +} + +static void smb_put_super(struct super_block *sb) { struct smb_sb_info *server = SMB_SB(sb); @@ -461,15 +475,7 @@ smb_put_super(struct super_block *sb) kill_proc(server->conn_pid, SIGTERM, 1); smb_kfree(server->ops); - - if (server->remote_nls) { - unload_nls(server->remote_nls); - server->remote_nls = NULL; - } - if (server->local_nls) { - unload_nls(server->local_nls); - server->local_nls = NULL; - } + smb_unload_nls(server); sb->s_fs_info = NULL; smb_unlock_server(server); smb_kfree(server); @@ -545,10 +551,8 @@ int smb_fill_super(struct super_block *s if (ver == SMB_MOUNT_OLDVERSION) { mnt->version = oldmnt->version; - /* FIXME: is this enough to convert uid/gid's ? */ - mnt->mounted_uid = oldmnt->mounted_uid; - mnt->uid = oldmnt->uid; - mnt->gid = oldmnt->gid; + mnt->uid = low2highuid(oldmnt->uid); + mnt->gid = low2highuid(oldmnt->gid); mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG; mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR; @@ -557,9 +561,8 @@ int smb_fill_super(struct super_block *s } else { if (parse_options(mnt, raw_data)) goto out_bad_option; - - mnt->mounted_uid = current->uid; } + mnt->mounted_uid = current->uid; smb_setcodepage(server, &mnt->codepage); /* @@ -571,6 +574,11 @@ int smb_fill_super(struct super_block *s else if (mnt->flags & SMB_MOUNT_DIRATTR) printk("SMBFS: Using dir ff getattr\n"); + if (smbiod_register_server(server) < 0) { + printk(KERN_ERR "smbfs: failed to start smbiod\n"); + goto out_no_smbiod; + } + /* * Keep the super block locked while we get the root inode. */ @@ -584,12 +592,12 @@ int smb_fill_super(struct super_block *s goto out_no_root; smb_new_dentry(sb->s_root); - smbiod_register_server(server); - return 0; out_no_root: iput(root_inode); +out_no_smbiod: + smb_unload_nls(server); out_bad_option: smb_kfree(mem); out_no_mem: diff -puN fs/smbfs/Makefile~smbfs-fixes fs/smbfs/Makefile --- 25/fs/smbfs/Makefile~smbfs-fixes 2003-09-13 11:32:36.000000000 -0700 +++ 25-akpm/fs/smbfs/Makefile 2003-09-13 11:32:36.000000000 -0700 @@ -32,6 +32,8 @@ proto: @echo >> proto2.h " */" @echo >> proto2.h "" @echo >> proto2.h "struct smb_request;" + @echo >> proto2.h "struct sock;" + @echo >> proto2.h "struct statfs;" @echo >> proto2.h "" cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h mv proto2.h proto.h diff -puN fs/smbfs/proto.h~smbfs-fixes fs/smbfs/proto.h --- 25/fs/smbfs/proto.h~smbfs-fixes 2003-09-13 11:32:36.000000000 -0700 +++ 25-akpm/fs/smbfs/proto.h 2003-09-13 11:32:36.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Autogenerated with cproto on: Sun Sep 29 21:48:59 CEST 2002 + * Autogenerated with cproto on: Sat Sep 13 17:18:51 CEST 2003 */ struct smb_request; @@ -34,6 +34,7 @@ extern int smb_proc_read_link(struct smb extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath); extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); extern int smb_proc_query_cifsunix(struct smb_sb_info *server); +extern void smb_install_null_ops(struct smb_ops *ops); /* dir.c */ extern struct file_operations smb_dir_operations; extern struct inode_operations smb_dir_inode_operations; @@ -71,7 +72,7 @@ extern struct inode_operations smb_file_ extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); /* smbiod.c */ extern void smbiod_wake_up(void); -extern void smbiod_register_server(struct smb_sb_info *server); +extern int smbiod_register_server(struct smb_sb_info *server); extern void smbiod_unregister_server(struct smb_sb_info *server); extern void smbiod_flush(struct smb_sb_info *server); extern int smbiod_retry(struct smb_sb_info *server); diff -puN fs/smbfs/smbiod.c~smbfs-fixes fs/smbfs/smbiod.c --- 25/fs/smbfs/smbiod.c~smbfs-fixes 2003-09-13 11:32:36.000000000 -0700 +++ 25-akpm/fs/smbfs/smbiod.c 2003-09-13 11:32:36.000000000 -0700 @@ -49,7 +49,7 @@ static spinlock_t servers_lock = SPIN_LO static long smbiod_flags; static int smbiod(void *); -static void smbiod_start(void); +static int smbiod_start(void); /* * called when there's work for us to do @@ -65,30 +65,36 @@ void smbiod_wake_up() /* * start smbiod if none is running */ -static void smbiod_start() +static int smbiod_start() { pid_t pid; if (smbiod_state != SMBIOD_DEAD) - return; + return 0; smbiod_state = SMBIOD_STARTING; + __module_get(THIS_MODULE); spin_unlock(&servers_lock); pid = kernel_thread(smbiod, NULL, 0); + if (pid < 0) + module_put(THIS_MODULE); spin_lock(&servers_lock); - smbiod_state = SMBIOD_RUNNING; + smbiod_state = pid < 0 ? SMBIOD_DEAD : SMBIOD_RUNNING; smbiod_pid = pid; + return pid; } /* * register a server & start smbiod if necessary */ -void smbiod_register_server(struct smb_sb_info *server) +int smbiod_register_server(struct smb_sb_info *server) { + int ret; spin_lock(&servers_lock); list_add(&server->entry, &smb_servers); VERBOSE("%p\n", server); - smbiod_start(); + ret = smbiod_start(); spin_unlock(&servers_lock); + return ret; } /* @@ -282,7 +288,6 @@ out: */ static int smbiod(void *unused) { - MOD_INC_USE_COUNT; daemonize("smbiod"); allow_signal(SIGKILL); @@ -330,6 +335,5 @@ static int smbiod(void *unused) } VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid); - MOD_DEC_USE_COUNT; - return 0; + module_put_and_exit(0); } diff -puN include/linux/smb_mount.h~smbfs-fixes include/linux/smb_mount.h --- 25/include/linux/smb_mount.h~smbfs-fixes 2003-09-13 11:32:36.000000000 -0700 +++ 25-akpm/include/linux/smb_mount.h 2003-09-13 11:32:36.000000000 -0700 @@ -43,11 +43,11 @@ struct smb_mount_data { struct smb_mount_data_kernel { int version; - __kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */ - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_mode_t file_mode; - __kernel_mode_t dir_mode; + uid_t mounted_uid; /* Who may umount() this filesystem? */ + uid_t uid; + gid_t gid; + mode_t file_mode; + mode_t dir_mode; u32 flags; _