2003-09-13 15:32:29

by Urban Widmark

[permalink] [raw]
Subject: [patch] smbfs module unload and highuid


Hello,

I haven't been doing much smbfs work recently, but here are some bugfixes:

- 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.

Patch vs 2.6.0-test5, please apply.

/Urban


diff -urN -X exclude linux-2.6.0-test5-orig/fs/smbfs/Makefile linux-2.6.0-test5-smbfs/fs/smbfs/Makefile
--- linux-2.6.0-test5-orig/fs/smbfs/Makefile Mon Sep 8 21:49:58 2003
+++ linux-2.6.0-test5-smbfs/fs/smbfs/Makefile Sat Sep 13 17:14:04 2003
@@ -32,6 +32,8 @@
@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 -urN -X exclude linux-2.6.0-test5-orig/fs/smbfs/inode.c linux-2.6.0-test5-smbfs/fs/smbfs/inode.c
--- linux-2.6.0-test5-orig/fs/smbfs/inode.c Mon Sep 8 21:49:53 2003
+++ linux-2.6.0-test5-smbfs/fs/smbfs/inode.c Sat Sep 13 16:53:10 2003
@@ -25,6 +25,7 @@
#include <linux/mount.h>
#include <linux/net.h>
#include <linux/vfs.h>
+#include <linux/highuid.h>
#include <linux/smb_fs.h>
#include <linux/smbno.h>
#include <linux/smb_mount.h>
@@ -447,6 +448,19 @@
}

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 @@
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 @@
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 @@
} 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 @@
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 @@
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 -urN -X exclude linux-2.6.0-test5-orig/fs/smbfs/proto.h linux-2.6.0-test5-smbfs/fs/smbfs/proto.h
--- linux-2.6.0-test5-orig/fs/smbfs/proto.h Mon Sep 8 21:50:07 2003
+++ linux-2.6.0-test5-smbfs/fs/smbfs/proto.h Sat Sep 13 17:18:52 2003
@@ -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_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 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 -urN -X exclude linux-2.6.0-test5-orig/fs/smbfs/smbiod.c linux-2.6.0-test5-smbfs/fs/smbfs/smbiod.c
--- linux-2.6.0-test5-orig/fs/smbfs/smbiod.c Mon Sep 8 21:50:09 2003
+++ linux-2.6.0-test5-smbfs/fs/smbfs/smbiod.c Sat Sep 13 16:54:02 2003
@@ -49,7 +49,7 @@
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 @@
/*
* 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 @@
*/
static int smbiod(void *unused)
{
- MOD_INC_USE_COUNT;
daemonize("smbiod");

allow_signal(SIGKILL);
@@ -330,6 +335,5 @@
}

VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid);
- MOD_DEC_USE_COUNT;
- return 0;
+ module_put_and_exit(0);
}
diff -urN -X exclude linux-2.6.0-test5-orig/include/linux/smb_mount.h linux-2.6.0-test5-smbfs/include/linux/smb_mount.h
--- linux-2.6.0-test5-orig/include/linux/smb_mount.h Mon Sep 8 21:49:51 2003
+++ linux-2.6.0-test5-smbfs/include/linux/smb_mount.h Sat Sep 13 12:34:31 2003
@@ -43,11 +43,11 @@
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;