Skip to content

Commit 2004e41

Browse files
Paulo Alcantaragregkh
authored andcommitted
smb: client: instantiate when creating SFU files
[ Upstream commit c6ff459 ] In cifs_sfu_make_node(), on success, instantiate rather than leave it with dentry unhashed negative to support callers that expect mknod(2) to always instantiate. This fixes the following test case: mount.cifs //srv/share /mnt -o ...,sfu mkfifo /mnt/fifo ./xfstests/ltp/growfiles -b -W test -e 1 -u -i 0 -L 30 /mnt/fifo ... BUG: unable to handle page fault for address: 000000034cec4e58 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 1 PREEMPT SMP PTI CPU: 0 PID: 138098 Comm: growfiles Kdump: loaded Not tainted 5.14.0-436.3987_1240945149.el9.x86_64 #1 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 RIP: 0010:_raw_callee_save__kvm_vcpu_is_preempted+0x0/0x20 Code: e8 15 d9 61 00 e9 63 ff ff ff 41 bd ea ff ff ff e9 58 ff ff ff e8 d0 71 c0 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 <48> 8b 04 fd 60 2b c1 99 80 b8 90 50 03 00 00 0f 95 c0 c3 cc cc cc RSP: 0018:ffffb6a143cf7cf8 EFLAGS: 00010206 RAX: ffff8a9bc30fb038 RBX: ffff8a9bc666a200 RCX: ffff8a9cc0260000 RDX: 00000000736f622e RSI: ffff8a9bc30fb038 RDI: 000000007665645f RBP: ffffb6a143cf7d70 R08: 0000000000001000 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000000 R12: ffff8a9bc666a200 R13: 0000559a302a12b0 R14: 0000000000001000 R15: 0000000000000000 FS: 00007fbed1dbb740(0000) GS:ffff8a9cf0000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000034cec4e58 CR3: 0000000128ec6006 CR4: 0000000000770ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <TASK> ? show_trace_log_lvl+0x1c4/0x2df ? show_trace_log_lvl+0x1c4/0x2df ? __mutex_lock.constprop.0+0x5f7/0x6a0 ? __die_body.cold+0x8/0xd ? page_fault_oops+0x134/0x170 ? exc_page_fault+0x62/0x150 ? asm_exc_page_fault+0x22/0x30 ? _pfx_raw_callee_save__kvm_vcpu_is_preempted+0x10/0x10 __mutex_lock.constprop.0+0x5f7/0x6a0 ? __mod_memcg_lruvec_state+0x84/0xd0 pipe_write+0x47/0x650 ? do_anonymous_page+0x258/0x410 ? inode_security+0x22/0x60 ? selinux_file_permission+0x108/0x150 vfs_write+0x2cb/0x410 ksys_write+0x5f/0xe0 do_syscall_64+0x5c/0xf0 ? syscall_exit_to_user_mode+0x22/0x40 ? do_syscall_64+0x6b/0xf0 ? sched_clock_cpu+0x9/0xc0 ? exc_page_fault+0x62/0x150 entry_SYSCALL_64_after_hwframe+0x6e/0x76 Cc: stable@vger.kernel.org Fixes: 72bc63f ("smb3: fix creating FIFOs when mounting with "sfu" mount option") Suggested-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 01bce09 commit 2004e41

File tree

1 file changed

+55
-39
lines changed

1 file changed

+55
-39
lines changed

fs/smb/client/smb2ops.c

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4956,68 +4956,84 @@ static int smb2_next_header(struct TCP_Server_Info *server, char *buf,
49564956
return 0;
49574957
}
49584958

4959-
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
4960-
struct dentry *dentry, struct cifs_tcon *tcon,
4961-
const char *full_path, umode_t mode, dev_t dev)
4959+
static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
4960+
struct dentry *dentry, struct cifs_tcon *tcon,
4961+
const char *full_path, umode_t mode, dev_t dev)
49624962
{
4963-
struct cifs_open_info_data buf = {};
49644963
struct TCP_Server_Info *server = tcon->ses->server;
49654964
struct cifs_open_parms oparms;
49664965
struct cifs_io_parms io_parms = {};
49674966
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
49684967
struct cifs_fid fid;
49694968
unsigned int bytes_written;
4970-
struct win_dev *pdev;
4969+
struct win_dev pdev = {};
49714970
struct kvec iov[2];
49724971
__u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
49734972
int rc;
49744973

4975-
if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
4974+
switch (mode & S_IFMT) {
4975+
case S_IFCHR:
4976+
strscpy(pdev.type, "IntxCHR", strlen("IntxChr"));
4977+
pdev.major = cpu_to_le64(MAJOR(dev));
4978+
pdev.minor = cpu_to_le64(MINOR(dev));
4979+
break;
4980+
case S_IFBLK:
4981+
strscpy(pdev.type, "IntxBLK", strlen("IntxBLK"));
4982+
pdev.major = cpu_to_le64(MAJOR(dev));
4983+
pdev.minor = cpu_to_le64(MINOR(dev));
4984+
break;
4985+
case S_IFIFO:
4986+
strscpy(pdev.type, "LnxFIFO", strlen("LnxFIFO"));
4987+
break;
4988+
default:
49764989
return -EPERM;
4990+
}
49774991

4978-
oparms = (struct cifs_open_parms) {
4979-
.tcon = tcon,
4980-
.cifs_sb = cifs_sb,
4981-
.desired_access = GENERIC_WRITE,
4982-
.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
4983-
CREATE_OPTION_SPECIAL),
4984-
.disposition = FILE_CREATE,
4985-
.path = full_path,
4986-
.fid = &fid,
4987-
};
4992+
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE,
4993+
FILE_CREATE, CREATE_NOT_DIR |
4994+
CREATE_OPTION_SPECIAL, ACL_NO_MODE);
4995+
oparms.fid = &fid;
49884996

4989-
rc = server->ops->open(xid, &oparms, &oplock, &buf);
4997+
rc = server->ops->open(xid, &oparms, &oplock, NULL);
49904998
if (rc)
49914999
return rc;
49925000

4993-
/*
4994-
* BB Do not bother to decode buf since no local inode yet to put
4995-
* timestamps in, but we can reuse it safely.
4996-
*/
4997-
pdev = (struct win_dev *)&buf.fi;
49985001
io_parms.pid = current->tgid;
49995002
io_parms.tcon = tcon;
5000-
io_parms.length = sizeof(*pdev);
5001-
iov[1].iov_base = pdev;
5002-
iov[1].iov_len = sizeof(*pdev);
5003-
if (S_ISCHR(mode)) {
5004-
memcpy(pdev->type, "IntxCHR", 8);
5005-
pdev->major = cpu_to_le64(MAJOR(dev));
5006-
pdev->minor = cpu_to_le64(MINOR(dev));
5007-
} else if (S_ISBLK(mode)) {
5008-
memcpy(pdev->type, "IntxBLK", 8);
5009-
pdev->major = cpu_to_le64(MAJOR(dev));
5010-
pdev->minor = cpu_to_le64(MINOR(dev));
5011-
} else if (S_ISFIFO(mode)) {
5012-
memcpy(pdev->type, "LnxFIFO", 8);
5013-
}
5003+
io_parms.length = sizeof(pdev);
5004+
iov[1].iov_base = &pdev;
5005+
iov[1].iov_len = sizeof(pdev);
50145006

50155007
rc = server->ops->sync_write(xid, &fid, &io_parms,
50165008
&bytes_written, iov, 1);
50175009
server->ops->close(xid, tcon, &fid);
5018-
d_drop(dentry);
5019-
/* FIXME: add code here to set EAs */
5020-
cifs_free_open_info(&buf);
5010+
return rc;
5011+
}
5012+
5013+
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
5014+
struct dentry *dentry, struct cifs_tcon *tcon,
5015+
const char *full_path, umode_t mode, dev_t dev)
5016+
{
5017+
struct inode *new = NULL;
5018+
int rc;
5019+
5020+
rc = __cifs_sfu_make_node(xid, inode, dentry, tcon,
5021+
full_path, mode, dev);
5022+
if (rc)
5023+
return rc;
5024+
5025+
if (tcon->posix_extensions) {
5026+
rc = smb311_posix_get_inode_info(&new, full_path, NULL,
5027+
inode->i_sb, xid);
5028+
} else if (tcon->unix_ext) {
5029+
rc = cifs_get_inode_info_unix(&new, full_path,
5030+
inode->i_sb, xid);
5031+
} else {
5032+
rc = cifs_get_inode_info(&new, full_path, NULL,
5033+
inode->i_sb, xid, NULL);
5034+
}
5035+
if (!rc)
5036+
d_instantiate(dentry, new);
50215037
return rc;
50225038
}
50235039

0 commit comments

Comments
 (0)