Loading fs/smb/client/smb2inode.c +33 −0 Original line number Diff line number Diff line Loading @@ -1053,3 +1053,36 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, } return rc ? ERR_PTR(rc) : new; } int smb2_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, u32 *tag, struct kvec *rsp, int *rsp_buftype) { struct cifs_open_info_data data = {}; struct cifsFileInfo *cfile; struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), }; int rc; cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); cifs_get_readable_path(tcon, full_path, &cfile); rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE, &in_iov, &(int){SMB2_OP_GET_REPARSE}, 1, cfile, NULL, NULL, NULL, NULL); if (rc) goto out; *tag = data.reparse.tag; *rsp = data.reparse.io.iov; *rsp_buftype = data.reparse.io.buftype; memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov)); data.reparse.io.buftype = CIFS_NO_BUFFER; out: cifs_free_open_info(&data); return rc; } fs/smb/client/smb2ops.c +0 −139 Original line number Diff line number Diff line Loading @@ -2997,145 +2997,6 @@ static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, return parse_reparse_point(buf, plen, cifs_sb, true, data); } static int smb2_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, u32 *tag, struct kvec *rsp, int *rsp_buftype) { struct smb2_compound_vars *vars; int rc; __le16 *utf16_path = NULL; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct cifs_open_parms oparms; struct cifs_fid fid; struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); int flags = CIFS_CP_CREATE_CLOSE_OP; struct smb_rqst *rqst; int resp_buftype[3]; struct kvec *rsp_iov; struct smb2_ioctl_rsp *ioctl_rsp; struct reparse_data_buffer *reparse_buf; u32 off, count, len; cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; vars = kzalloc(sizeof(*vars), GFP_KERNEL); if (!vars) { rc = -ENOMEM; goto out_free_path; } rqst = vars->rqst; rsp_iov = vars->rsp_iov; /* * setup smb2open - TODO add optimization to call cifs_get_readable_path * to see if there is a handle already open that we can use */ rqst[0].rq_iov = vars->open_iov; rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; oparms = (struct cifs_open_parms) { .tcon = tcon, .path = full_path, .desired_access = FILE_READ_ATTRIBUTES, .disposition = FILE_OPEN, .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT), .fid = &fid, }; rc = SMB2_open_init(tcon, server, &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto query_rp_exit; smb2_set_next_command(tcon, &rqst[0]); /* IOCTL */ rqst[1].rq_iov = vars->io_iov; rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0, CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - MAX_SMB2_CLOSE_RESPONSE_SIZE); if (rc) goto query_rp_exit; smb2_set_next_command(tcon, &rqst[1]); smb2_set_related(&rqst[1]); /* Close */ rqst[2].rq_iov = &vars->close_iov; rqst[2].rq_nvec = 1; rc = SMB2_close_init(tcon, server, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto query_rp_exit; smb2_set_related(&rqst[2]); rc = compound_send_recv(xid, tcon->ses, server, flags, 3, rqst, resp_buftype, rsp_iov); ioctl_rsp = rsp_iov[1].iov_base; /* * Open was successful and we got an ioctl response. */ if (rc == 0) { /* See MS-FSCC 2.3.23 */ off = le32_to_cpu(ioctl_rsp->OutputOffset); count = le32_to_cpu(ioctl_rsp->OutputCount); if (check_add_overflow(off, count, &len) || len > rsp_iov[1].iov_len) { cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", __func__, off, count); rc = -EIO; goto query_rp_exit; } reparse_buf = (void *)((u8 *)ioctl_rsp + off); len = sizeof(*reparse_buf); if (count < len || count < le16_to_cpu(reparse_buf->ReparseDataLength) + len) { cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", __func__, off, count); rc = -EIO; goto query_rp_exit; } *tag = le32_to_cpu(reparse_buf->ReparseTag); *rsp = rsp_iov[1]; *rsp_buftype = resp_buftype[1]; resp_buftype[1] = CIFS_NO_BUFFER; } query_rp_exit: SMB2_open_free(&rqst[0]); SMB2_ioctl_free(&rqst[1]); SMB2_close_free(&rqst[2]); free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); kfree(vars); out_free_path: kfree(utf16_path); return rc; } static struct cifs_ntsd * get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb, const struct cifs_fid *cifsfid, u32 *pacllen, u32 info) Loading fs/smb/client/smb2proto.h +6 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,12 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, struct cifs_tcon *tcon, const char *full_path, struct kvec *iov); int smb2_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, u32 *tag, struct kvec *rsp, int *rsp_buftype); int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, Loading Loading
fs/smb/client/smb2inode.c +33 −0 Original line number Diff line number Diff line Loading @@ -1053,3 +1053,36 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, } return rc ? ERR_PTR(rc) : new; } int smb2_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, u32 *tag, struct kvec *rsp, int *rsp_buftype) { struct cifs_open_info_data data = {}; struct cifsFileInfo *cfile; struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), }; int rc; cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); cifs_get_readable_path(tcon, full_path, &cfile); rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE, &in_iov, &(int){SMB2_OP_GET_REPARSE}, 1, cfile, NULL, NULL, NULL, NULL); if (rc) goto out; *tag = data.reparse.tag; *rsp = data.reparse.io.iov; *rsp_buftype = data.reparse.io.buftype; memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov)); data.reparse.io.buftype = CIFS_NO_BUFFER; out: cifs_free_open_info(&data); return rc; }
fs/smb/client/smb2ops.c +0 −139 Original line number Diff line number Diff line Loading @@ -2997,145 +2997,6 @@ static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, return parse_reparse_point(buf, plen, cifs_sb, true, data); } static int smb2_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, u32 *tag, struct kvec *rsp, int *rsp_buftype) { struct smb2_compound_vars *vars; int rc; __le16 *utf16_path = NULL; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct cifs_open_parms oparms; struct cifs_fid fid; struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); int flags = CIFS_CP_CREATE_CLOSE_OP; struct smb_rqst *rqst; int resp_buftype[3]; struct kvec *rsp_iov; struct smb2_ioctl_rsp *ioctl_rsp; struct reparse_data_buffer *reparse_buf; u32 off, count, len; cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; vars = kzalloc(sizeof(*vars), GFP_KERNEL); if (!vars) { rc = -ENOMEM; goto out_free_path; } rqst = vars->rqst; rsp_iov = vars->rsp_iov; /* * setup smb2open - TODO add optimization to call cifs_get_readable_path * to see if there is a handle already open that we can use */ rqst[0].rq_iov = vars->open_iov; rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; oparms = (struct cifs_open_parms) { .tcon = tcon, .path = full_path, .desired_access = FILE_READ_ATTRIBUTES, .disposition = FILE_OPEN, .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT), .fid = &fid, }; rc = SMB2_open_init(tcon, server, &rqst[0], &oplock, &oparms, utf16_path); if (rc) goto query_rp_exit; smb2_set_next_command(tcon, &rqst[0]); /* IOCTL */ rqst[1].rq_iov = vars->io_iov; rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; rc = SMB2_ioctl_init(tcon, server, &rqst[1], COMPOUND_FID, COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0, CIFSMaxBufSize - MAX_SMB2_CREATE_RESPONSE_SIZE - MAX_SMB2_CLOSE_RESPONSE_SIZE); if (rc) goto query_rp_exit; smb2_set_next_command(tcon, &rqst[1]); smb2_set_related(&rqst[1]); /* Close */ rqst[2].rq_iov = &vars->close_iov; rqst[2].rq_nvec = 1; rc = SMB2_close_init(tcon, server, &rqst[2], COMPOUND_FID, COMPOUND_FID, false); if (rc) goto query_rp_exit; smb2_set_related(&rqst[2]); rc = compound_send_recv(xid, tcon->ses, server, flags, 3, rqst, resp_buftype, rsp_iov); ioctl_rsp = rsp_iov[1].iov_base; /* * Open was successful and we got an ioctl response. */ if (rc == 0) { /* See MS-FSCC 2.3.23 */ off = le32_to_cpu(ioctl_rsp->OutputOffset); count = le32_to_cpu(ioctl_rsp->OutputCount); if (check_add_overflow(off, count, &len) || len > rsp_iov[1].iov_len) { cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", __func__, off, count); rc = -EIO; goto query_rp_exit; } reparse_buf = (void *)((u8 *)ioctl_rsp + off); len = sizeof(*reparse_buf); if (count < len || count < le16_to_cpu(reparse_buf->ReparseDataLength) + len) { cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", __func__, off, count); rc = -EIO; goto query_rp_exit; } *tag = le32_to_cpu(reparse_buf->ReparseTag); *rsp = rsp_iov[1]; *rsp_buftype = resp_buftype[1]; resp_buftype[1] = CIFS_NO_BUFFER; } query_rp_exit: SMB2_open_free(&rqst[0]); SMB2_ioctl_free(&rqst[1]); SMB2_close_free(&rqst[2]); free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); kfree(vars); out_free_path: kfree(utf16_path); return rc; } static struct cifs_ntsd * get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb, const struct cifs_fid *cifsfid, u32 *pacllen, u32 info) Loading
fs/smb/client/smb2proto.h +6 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,12 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, struct cifs_tcon *tcon, const char *full_path, struct kvec *iov); int smb2_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, u32 *tag, struct kvec *rsp, int *rsp_buftype); int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, Loading