Commit c506da41 authored by Urban Widmark's avatar Urban Widmark Committed by Linus Torvalds

[PATCH] smbfs module unload and highuid

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.
parent 851cbb5f
...@@ -32,6 +32,8 @@ proto: ...@@ -32,6 +32,8 @@ proto:
@echo >> proto2.h " */" @echo >> proto2.h " */"
@echo >> proto2.h "" @echo >> proto2.h ""
@echo >> proto2.h "struct smb_request;" @echo >> proto2.h "struct smb_request;"
@echo >> proto2.h "struct sock;"
@echo >> proto2.h "struct statfs;"
@echo >> proto2.h "" @echo >> proto2.h ""
cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h
mv proto2.h proto.h mv proto2.h proto.h
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/highuid.h>
#include <linux/smb_fs.h> #include <linux/smb_fs.h>
#include <linux/smbno.h> #include <linux/smbno.h>
#include <linux/smb_mount.h> #include <linux/smb_mount.h>
...@@ -446,6 +447,19 @@ smb_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -446,6 +447,19 @@ smb_show_options(struct seq_file *s, struct vfsmount *m)
return 0; return 0;
} }
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 static void
smb_put_super(struct super_block *sb) smb_put_super(struct super_block *sb)
{ {
...@@ -461,15 +475,7 @@ smb_put_super(struct super_block *sb) ...@@ -461,15 +475,7 @@ smb_put_super(struct super_block *sb)
kill_proc(server->conn_pid, SIGTERM, 1); kill_proc(server->conn_pid, SIGTERM, 1);
smb_kfree(server->ops); smb_kfree(server->ops);
smb_unload_nls(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;
}
sb->s_fs_info = NULL; sb->s_fs_info = NULL;
smb_unlock_server(server); smb_unlock_server(server);
smb_kfree(server); smb_kfree(server);
...@@ -545,10 +551,8 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -545,10 +551,8 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
if (ver == SMB_MOUNT_OLDVERSION) { if (ver == SMB_MOUNT_OLDVERSION) {
mnt->version = oldmnt->version; mnt->version = oldmnt->version;
/* FIXME: is this enough to convert uid/gid's ? */ mnt->uid = low2highuid(oldmnt->uid);
mnt->mounted_uid = oldmnt->mounted_uid; mnt->gid = low2highuid(oldmnt->gid);
mnt->uid = oldmnt->uid;
mnt->gid = oldmnt->gid;
mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG; mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR; mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
...@@ -557,9 +561,8 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -557,9 +561,8 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
} else { } else {
if (parse_options(mnt, raw_data)) if (parse_options(mnt, raw_data))
goto out_bad_option; goto out_bad_option;
mnt->mounted_uid = current->uid;
} }
mnt->mounted_uid = current->uid;
smb_setcodepage(server, &mnt->codepage); smb_setcodepage(server, &mnt->codepage);
/* /*
...@@ -571,6 +574,11 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -571,6 +574,11 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
else if (mnt->flags & SMB_MOUNT_DIRATTR) else if (mnt->flags & SMB_MOUNT_DIRATTR)
printk("SMBFS: Using dir ff getattr\n"); 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. * Keep the super block locked while we get the root inode.
*/ */
...@@ -584,12 +592,12 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -584,12 +592,12 @@ int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
goto out_no_root; goto out_no_root;
smb_new_dentry(sb->s_root); smb_new_dentry(sb->s_root);
smbiod_register_server(server);
return 0; return 0;
out_no_root: out_no_root:
iput(root_inode); iput(root_inode);
out_no_smbiod:
smb_unload_nls(server);
out_bad_option: out_bad_option:
smb_kfree(mem); smb_kfree(mem);
out_no_mem: out_no_mem:
......
/* /*
* 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; struct smb_request;
...@@ -34,6 +34,7 @@ extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char ...@@ -34,6 +34,7 @@ extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char
extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath); 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_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 int smb_proc_query_cifsunix(struct smb_sb_info *server);
extern void smb_install_null_ops(struct smb_ops *ops);
/* dir.c */ /* dir.c */
extern struct file_operations smb_dir_operations; extern struct file_operations smb_dir_operations;
extern struct inode_operations smb_dir_inode_operations; extern struct inode_operations smb_dir_inode_operations;
...@@ -71,7 +72,7 @@ extern struct inode_operations smb_file_inode_operations; ...@@ -71,7 +72,7 @@ extern struct inode_operations smb_file_inode_operations;
extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
/* smbiod.c */ /* smbiod.c */
extern void smbiod_wake_up(void); 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_unregister_server(struct smb_sb_info *server);
extern void smbiod_flush(struct smb_sb_info *server); extern void smbiod_flush(struct smb_sb_info *server);
extern int smbiod_retry(struct smb_sb_info *server); extern int smbiod_retry(struct smb_sb_info *server);
......
...@@ -49,7 +49,7 @@ static spinlock_t servers_lock = SPIN_LOCK_UNLOCKED; ...@@ -49,7 +49,7 @@ static spinlock_t servers_lock = SPIN_LOCK_UNLOCKED;
static long smbiod_flags; static long smbiod_flags;
static int smbiod(void *); static int smbiod(void *);
static void smbiod_start(void); static int smbiod_start(void);
/* /*
* called when there's work for us to do * called when there's work for us to do
...@@ -65,30 +65,36 @@ void smbiod_wake_up() ...@@ -65,30 +65,36 @@ void smbiod_wake_up()
/* /*
* start smbiod if none is running * start smbiod if none is running
*/ */
static void smbiod_start() static int smbiod_start()
{ {
pid_t pid; pid_t pid;
if (smbiod_state != SMBIOD_DEAD) if (smbiod_state != SMBIOD_DEAD)
return; return 0;
smbiod_state = SMBIOD_STARTING; smbiod_state = SMBIOD_STARTING;
__module_get(THIS_MODULE);
spin_unlock(&servers_lock); spin_unlock(&servers_lock);
pid = kernel_thread(smbiod, NULL, 0); pid = kernel_thread(smbiod, NULL, 0);
if (pid < 0)
module_put(THIS_MODULE);
spin_lock(&servers_lock); spin_lock(&servers_lock);
smbiod_state = SMBIOD_RUNNING; smbiod_state = pid < 0 ? SMBIOD_DEAD : SMBIOD_RUNNING;
smbiod_pid = pid; smbiod_pid = pid;
return pid;
} }
/* /*
* register a server & start smbiod if necessary * 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); spin_lock(&servers_lock);
list_add(&server->entry, &smb_servers); list_add(&server->entry, &smb_servers);
VERBOSE("%p\n", server); VERBOSE("%p\n", server);
smbiod_start(); ret = smbiod_start();
spin_unlock(&servers_lock); spin_unlock(&servers_lock);
return ret;
} }
/* /*
...@@ -282,7 +288,6 @@ static void smbiod_doio(struct smb_sb_info *server) ...@@ -282,7 +288,6 @@ static void smbiod_doio(struct smb_sb_info *server)
*/ */
static int smbiod(void *unused) static int smbiod(void *unused)
{ {
MOD_INC_USE_COUNT;
daemonize("smbiod"); daemonize("smbiod");
allow_signal(SIGKILL); allow_signal(SIGKILL);
...@@ -330,6 +335,5 @@ static int smbiod(void *unused) ...@@ -330,6 +335,5 @@ static int smbiod(void *unused)
} }
VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid); VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid);
MOD_DEC_USE_COUNT; module_put_and_exit(0);
return 0;
} }
...@@ -43,11 +43,11 @@ struct smb_mount_data { ...@@ -43,11 +43,11 @@ struct smb_mount_data {
struct smb_mount_data_kernel { struct smb_mount_data_kernel {
int version; int version;
__kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */ uid_t mounted_uid; /* Who may umount() this filesystem? */
__kernel_uid_t uid; uid_t uid;
__kernel_gid_t gid; gid_t gid;
__kernel_mode_t file_mode; mode_t file_mode;
__kernel_mode_t dir_mode; mode_t dir_mode;
u32 flags; u32 flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment