From ce2ac52105aa663056dfc17966ebed1bf93e6e64 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 1 Feb 2013 15:11:01 -0500 Subject: cifs: ensure that cifs_get_root() only traverses directories Kjell Braden reported this oops: [ 833.211970] BUG: unable to handle kernel NULL pointer dereference at (null) [ 833.212816] IP: [< (null)>] (null) [ 833.213280] PGD 1b9b2067 PUD e9f7067 PMD 0 [ 833.213874] Oops: 0010 [#1] SMP [ 833.214344] CPU 0 [ 833.214458] Modules linked in: des_generic md4 nls_utf8 cifs vboxvideo drm snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq bnep rfcomm snd_timer bluetooth snd_seq_device ppdev snd vboxguest parport_pc joydev mac_hid soundcore snd_page_alloc psmouse i2c_piix4 serio_raw lp parport usbhid hid e1000 [ 833.215629] [ 833.215629] Pid: 1752, comm: mount.cifs Not tainted 3.0.0-rc7-bisectcifs-fec11dd9a0+ #18 innotek GmbH VirtualBox/VirtualBox [ 833.215629] RIP: 0010:[<0000000000000000>] [< (null)>] (null) [ 833.215629] RSP: 0018:ffff8800119c9c50 EFLAGS: 00010282 [ 833.215629] RAX: ffffffffa02186c0 RBX: ffff88000c427780 RCX: 0000000000000000 [ 833.215629] RDX: 0000000000000000 RSI: ffff88000c427780 RDI: ffff88000c4362e8 [ 833.215629] RBP: ffff8800119c9c88 R08: ffff88001fc15e30 R09: 00000000d69515c7 [ 833.215629] R10: ffffffffa0201972 R11: ffff88000e8f6a28 R12: ffff88000c4362e8 [ 833.215629] R13: 0000000000000000 R14: 0000000000000000 R15: ffff88001181aaa6 [ 833.215629] FS: 00007f2986171700(0000) GS:ffff88001fc00000(0000) knlGS:0000000000000000 [ 833.215629] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 833.215629] CR2: 0000000000000000 CR3: 000000001b982000 CR4: 00000000000006f0 [ 833.215629] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 833.215629] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 833.215629] Process mount.cifs (pid: 1752, threadinfo ffff8800119c8000, task ffff88001c1c16f0) [ 833.215629] Stack: [ 833.215629] ffffffff8116a9b5 ffff8800119c9c88 ffffffff81178075 0000000000000286 [ 833.215629] 0000000000000000 ffff88000c4276c0 ffff8800119c9ce8 ffff8800119c9cc8 [ 833.215629] ffffffff8116b06e ffff88001bc6fc00 ffff88000c4276c0 ffff88000c4276c0 [ 833.215629] Call Trace: [ 833.215629] [] ? d_alloc_and_lookup+0x45/0x90 [ 833.215629] [] ? d_lookup+0x35/0x60 [ 833.215629] [] __lookup_hash.part.14+0x9e/0xc0 [ 833.215629] [] lookup_one_len+0x146/0x1e0 [ 833.215629] [] ? _raw_spin_lock+0xe/0x20 [ 833.215629] [] cifs_do_mount+0x26d/0x500 [cifs] [ 833.215629] [] mount_fs+0x43/0x1b0 [ 833.215629] [] vfs_kern_mount+0x6a/0xd0 [ 833.215629] [] do_kern_mount+0x54/0x110 [ 833.215629] [] do_mount+0x262/0x840 [ 833.215629] [] ? __get_free_pages+0xe/0x50 [ 833.215629] [] ? copy_mount_options+0x3a/0x180 [ 833.215629] [] sys_mount+0x8d/0xe0 [ 833.215629] [] system_call_fastpath+0x16/0x1b [ 833.215629] Code: Bad RIP value. [ 833.215629] RIP [< (null)>] (null) [ 833.215629] RSP [ 833.215629] CR2: 0000000000000000 [ 833.238525] ---[ end trace ec00758b8d44f529 ]--- When walking down the path on the server, it's possible to hit a symlink. The path walking code assumes that the caller will handle that situation properly, but cifs_get_root() isn't set up for it. This patch prevents the oops by simply returning an error. A better solution would be to try and chase the symlinks here, but that's fairly complicated to handle. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=53221 Reported-and-tested-by: Kjell Braden Cc: stable Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4bad7b16271f..1a052c0eee8e 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -564,6 +564,11 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dentry = ERR_PTR(-ENOENT); break; } + if (!S_ISDIR(dir->i_mode)) { + dput(dentry); + dentry = ERR_PTR(-ENOTDIR); + break; + } /* skip separators */ while (*s == sep) -- cgit v1.2.3-55-g7522 From 07b92d0d570c903aeef4f3b76ebbdd728bc72805 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 18 Feb 2013 10:34:26 -0600 Subject: POSIX extensions disabled on client due to illegal O_EXCL flag sent to Samba Samba rejected libreoffice's attempt to open a file with illegal O_EXCL (without O_CREAT). Mask this flag off (as the local linux file system case does) for this case, so that we don't have disable Unix Extensions unnecessarily due to the Samba error (Samba server is also being fixed). See https://bugzilla.samba.org/show_bug.cgi?id=9519 Reviewed-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Steve French --- fs/cifs/file.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c16d2a018ab8..8c0d85577314 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -43,6 +43,7 @@ #include "cifs_fs_sb.h" #include "fscache.h" + static inline int cifs_convert_flags(unsigned int flags) { if ((flags & O_ACCMODE) == O_RDONLY) @@ -72,10 +73,15 @@ static u32 cifs_posix_convert_flags(unsigned int flags) else if ((flags & O_ACCMODE) == O_RDWR) posix_flags = SMB_O_RDWR; - if (flags & O_CREAT) + if (flags & O_CREAT) { posix_flags |= SMB_O_CREAT; - if (flags & O_EXCL) - posix_flags |= SMB_O_EXCL; + if (flags & O_EXCL) + posix_flags |= SMB_O_EXCL; + } else if (flags & O_EXCL) + cFYI(1, "Application %s pid %d has incorrectly set O_EXCL flag" + "but not O_CREAT on file open. Ignoring O_EXCL", + current->comm, current->tgid); + if (flags & O_TRUNC) posix_flags |= SMB_O_TRUNC; /* be safe and imply O_SYNC for O_DSYNC */ -- cgit v1.2.3-55-g7522 From 0b7bc84000d71f3647ca33ab1bf5bd928535c846 Mon Sep 17 00:00:00 2001 From: Martijn de Gouw Date: Wed, 24 Oct 2012 11:45:46 +0200 Subject: cifs: set MAY_SIGN when sec=krb5 Setting this secFlg allows usage of dfs where some servers require signing and others don't. Signed-off-by: Martijn de Gouw Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4474a57f30ab..54125e04fd0c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1031,7 +1031,7 @@ static int cifs_parse_security_flavors(char *value, switch (match_token(value, cifs_secflavor_tokens, args)) { case Opt_sec_krb5: - vol->secFlg |= CIFSSEC_MAY_KRB5; + vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_SIGN; break; case Opt_sec_krb5i: vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; -- cgit v1.2.3-55-g7522 From c51bb0ea40ca038da26b1fa7d450f4078124af03 Mon Sep 17 00:00:00 2001 From: Ouyang Maochun Date: Mon, 18 Feb 2013 09:54:52 -0600 Subject: cifs: bugfix for unreclaimed writeback pages in cifs_writev_requeue() Pages get the PG_writeback flag set before cifs sends its request to SMB server in cifs_writepages(), if the SMB service goes down, cifs may try to recommit the writing requests in cifs_writev_requeue(). However, it does not clean its PG_writeback flag and relaimed the pages even if it fails again in cifs_writev_requeue(), which may lead to the hanging of the processes accessing the cifs directory. This patch just cleans the PG_writeback flags and reclaims the pages under that circumstances. Steps to reproduce the bug(trying serveral times may trigger the issue): 1.Write from cifs client continuously.(e.g dd if=/dev/zero of=) 2.Stop SMB service from server.(e.g service smb stop) 3.Wait for two minutes, and then start SMB service from server.(e.g service smb start) 4.The processes which are accessing cifs directory may hang up. Signed-off-by: Ouyang Maochun Signed-off-by: Jiang Yong Tested-by: Zhang Xianwei Reviewed-by: Wang Liang Reviewed-by: Cai Qu Reviewed-by: Jiang Biao Reviewed-by: Jeff Layton Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 00e12f2d626b..7353bc5d73d7 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1909,8 +1909,11 @@ cifs_writev_requeue(struct cifs_writedata *wdata) } while (rc == -EAGAIN); for (i = 0; i < wdata->nr_pages; i++) { - if (rc != 0) + if (rc != 0) { SetPageError(wdata->pages[i]); + end_page_writeback(wdata->pages[i]); + page_cache_release(wdata->pages[i]); + } unlock_page(wdata->pages[i]); } -- cgit v1.2.3-55-g7522