Skip to content

Commit c6ff459

Browse files
Paulo Alcantarasmfrench
authored andcommitted
smb: client: instantiate when creating SFU files
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: [email protected] Fixes: 72bc63f ("smb3: fix creating FIFOs when mounting with "sfu" mount option") Suggested-by: Al Viro <[email protected]> Signed-off-by: Paulo Alcantara (Red Hat) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 28e0947 commit c6ff459

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
@@ -4964,68 +4964,84 @@ static int smb2_next_header(struct TCP_Server_Info *server, char *buf,
49644964
return 0;
49654965
}
49664966

4967-
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
4968-
struct dentry *dentry, struct cifs_tcon *tcon,
4969-
const char *full_path, umode_t mode, dev_t dev)
4967+
static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
4968+
struct dentry *dentry, struct cifs_tcon *tcon,
4969+
const char *full_path, umode_t mode, dev_t dev)
49704970
{
4971-
struct cifs_open_info_data buf = {};
49724971
struct TCP_Server_Info *server = tcon->ses->server;
49734972
struct cifs_open_parms oparms;
49744973
struct cifs_io_parms io_parms = {};
49754974
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
49764975
struct cifs_fid fid;
49774976
unsigned int bytes_written;
4978-
struct win_dev *pdev;
4977+
struct win_dev pdev = {};
49794978
struct kvec iov[2];
49804979
__u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
49814980
int rc;
49824981

4983-
if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
4982+
switch (mode & S_IFMT) {
4983+
case S_IFCHR:
4984+
strscpy(pdev.type, "IntxCHR");
4985+
pdev.major = cpu_to_le64(MAJOR(dev));
4986+
pdev.minor = cpu_to_le64(MINOR(dev));
4987+
break;
4988+
case S_IFBLK:
4989+
strscpy(pdev.type, "IntxBLK");
4990+
pdev.major = cpu_to_le64(MAJOR(dev));
4991+
pdev.minor = cpu_to_le64(MINOR(dev));
4992+
break;
4993+
case S_IFIFO:
4994+
strscpy(pdev.type, "LnxFIFO");
4995+
break;
4996+
default:
49844997
return -EPERM;
4998+
}
49854999

4986-
oparms = (struct cifs_open_parms) {
4987-
.tcon = tcon,
4988-
.cifs_sb = cifs_sb,
4989-
.desired_access = GENERIC_WRITE,
4990-
.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
4991-
CREATE_OPTION_SPECIAL),
4992-
.disposition = FILE_CREATE,
4993-
.path = full_path,
4994-
.fid = &fid,
4995-
};
5000+
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE,
5001+
FILE_CREATE, CREATE_NOT_DIR |
5002+
CREATE_OPTION_SPECIAL, ACL_NO_MODE);
5003+
oparms.fid = &fid;
49965004

4997-
rc = server->ops->open(xid, &oparms, &oplock, &buf);
5005+
rc = server->ops->open(xid, &oparms, &oplock, NULL);
49985006
if (rc)
49995007
return rc;
50005008

5001-
/*
5002-
* BB Do not bother to decode buf since no local inode yet to put
5003-
* timestamps in, but we can reuse it safely.
5004-
*/
5005-
pdev = (struct win_dev *)&buf.fi;
50065009
io_parms.pid = current->tgid;
50075010
io_parms.tcon = tcon;
5008-
io_parms.length = sizeof(*pdev);
5009-
iov[1].iov_base = pdev;
5010-
iov[1].iov_len = sizeof(*pdev);
5011-
if (S_ISCHR(mode)) {
5012-
memcpy(pdev->type, "IntxCHR", 8);
5013-
pdev->major = cpu_to_le64(MAJOR(dev));
5014-
pdev->minor = cpu_to_le64(MINOR(dev));
5015-
} else if (S_ISBLK(mode)) {
5016-
memcpy(pdev->type, "IntxBLK", 8);
5017-
pdev->major = cpu_to_le64(MAJOR(dev));
5018-
pdev->minor = cpu_to_le64(MINOR(dev));
5019-
} else if (S_ISFIFO(mode)) {
5020-
memcpy(pdev->type, "LnxFIFO", 8);
5021-
}
5011+
io_parms.length = sizeof(pdev);
5012+
iov[1].iov_base = &pdev;
5013+
iov[1].iov_len = sizeof(pdev);
50225014

50235015
rc = server->ops->sync_write(xid, &fid, &io_parms,
50245016
&bytes_written, iov, 1);
50255017
server->ops->close(xid, tcon, &fid);
5026-
d_drop(dentry);
5027-
/* FIXME: add code here to set EAs */
5028-
cifs_free_open_info(&buf);
5018+
return rc;
5019+
}
5020+
5021+
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
5022+
struct dentry *dentry, struct cifs_tcon *tcon,
5023+
const char *full_path, umode_t mode, dev_t dev)
5024+
{
5025+
struct inode *new = NULL;
5026+
int rc;
5027+
5028+
rc = __cifs_sfu_make_node(xid, inode, dentry, tcon,
5029+
full_path, mode, dev);
5030+
if (rc)
5031+
return rc;
5032+
5033+
if (tcon->posix_extensions) {
5034+
rc = smb311_posix_get_inode_info(&new, full_path, NULL,
5035+
inode->i_sb, xid);
5036+
} else if (tcon->unix_ext) {
5037+
rc = cifs_get_inode_info_unix(&new, full_path,
5038+
inode->i_sb, xid);
5039+
} else {
5040+
rc = cifs_get_inode_info(&new, full_path, NULL,
5041+
inode->i_sb, xid, NULL);
5042+
}
5043+
if (!rc)
5044+
d_instantiate(dentry, new);
50295045
return rc;
50305046
}
50315047

0 commit comments

Comments
 (0)