Commit 69dda305 authored by Aurelien Aptel's avatar Aurelien Aptel Committed by Steve French
Browse files

cifs: add SMB2_open() arg to return POSIX data



allows SMB2_open() callers to pass down a POSIX data buffer that will
trigger requesting POSIX create context and parsing the response into
the provided buffer.

Signed-off-by: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Reviewed-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
parent 3d519bd1
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -416,7 +416,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
	}

	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
		       NULL);
		       NULL, NULL);
	if (rc)
		goto qmf_out_open_fail;

@@ -470,7 +470,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
		       NULL);
		       NULL, NULL);
	if (rc) {
		kfree(utf16_path);
		return rc;
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
	smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;

	rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL,
		       NULL);
		       NULL, NULL);
	if (rc)
		goto out;

+15 −8
Original line number Diff line number Diff line
@@ -794,7 +794,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
		tcon->crfid.has_lease = true;
		smb2_parse_contexts(server, o_rsp,
				&oparms.fid->epoch,
				oparms.fid->lease_key, &oplock, NULL);
				    oparms.fid->lease_key, &oplock,
				    NULL, NULL);
	} else
		goto oshr_exit;

@@ -838,7 +839,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,

	if (no_cached_open)
		rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
			       NULL);
			       NULL, NULL);
	else
		rc = open_shroot(xid, tcon, cifs_sb, &fid);

@@ -878,7 +879,8 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
		       NULL, NULL);
	if (rc)
		return;

@@ -913,7 +915,8 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
		       NULL);
	if (rc) {
		kfree(utf16_path);
		return rc;
@@ -2122,7 +2125,8 @@ smb3_notify(const unsigned int xid, struct file *pfile,
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
		       NULL);
	if (rc)
		goto notify_exit;

@@ -2543,7 +2547,8 @@ smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
		       NULL, NULL);
	if (rc)
		return rc;

@@ -3028,7 +3033,8 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL,
		       NULL);
	kfree(utf16_path);
	if (!rc) {
		rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
@@ -3086,7 +3092,8 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
	oparms.fid = &fid;
	oparms.reconnect = false;

	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
		       NULL, NULL);
	kfree(utf16_path);
	if (!rc) {
		rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
+39 −16
Original line number Diff line number Diff line
@@ -1951,25 +1951,46 @@ parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
}

static void
parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info)
parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info,
		 struct create_posix_rsp *posix)
{
	/* struct create_posix_rsp *posix = (struct create_posix_rsp *)cc; */
	int sid_len;
	u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset);
	u8 *end = beg + le32_to_cpu(cc->DataLength);
	u8 *sid;

	/*
	 * TODO: Need to add parsing for the context and return. Can
	 * smb2_file_all_info hold POSIX data? Need to change the
	 * passed type from SMB2_open.
	 */
	printk_once(KERN_WARNING
		    "SMB3 3.11 POSIX response context not completed yet\n");
	memset(posix, 0, sizeof(*posix));

	posix->nlink = le32_to_cpu(*(__le32 *)(beg + 0));
	posix->reparse_tag = le32_to_cpu(*(__le32 *)(beg + 4));
	posix->mode = le32_to_cpu(*(__le32 *)(beg + 8));

	sid = beg + 12;
	sid_len = posix_info_sid_size(sid, end);
	if (sid_len < 0) {
		cifs_dbg(VFS, "bad owner sid in posix create response\n");
		return;
	}
	memcpy(&posix->owner, sid, sid_len);

	sid = sid + sid_len;
	sid_len = posix_info_sid_size(sid, end);
	if (sid_len < 0) {
		cifs_dbg(VFS, "bad group sid in posix create response\n");
		return;
	}
	memcpy(&posix->group, sid, sid_len);

	cifs_dbg(FYI, "nlink=%d mode=%o reparse_tag=%x\n",
		 posix->nlink, posix->mode, posix->reparse_tag);
}

void
smb2_parse_contexts(struct TCP_Server_Info *server,
		    struct smb2_create_rsp *rsp,
		    unsigned int *epoch, char *lease_key, __u8 *oplock,
		       struct smb2_file_all_info *buf)
		    struct smb2_file_all_info *buf,
		    struct create_posix_rsp *posix)
{
	char *data_offset;
	struct create_context *cc;
@@ -1999,8 +2020,9 @@ smb2_parse_contexts(struct TCP_Server_Info *server,
		    strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
			parse_query_id_ctxt(cc, buf);
		else if ((le16_to_cpu(cc->NameLength) == 16)) {
			if (memcmp(name, smb3_create_tag_posix, 16) == 0)
				parse_posix_ctxt(cc, buf);
			if (posix &&
			    memcmp(name, smb3_create_tag_posix, 16) == 0)
				parse_posix_ctxt(cc, buf, posix);
		}
		/* else {
			cifs_dbg(FYI, "Context not matched with len %d\n",
@@ -2725,6 +2747,7 @@ SMB2_open_free(struct smb_rqst *rqst)
int
SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
	  __u8 *oplock, struct smb2_file_all_info *buf,
	  struct create_posix_rsp *posix,
	  struct kvec *err_iov, int *buftype)
{
	struct smb_rqst rqst;
@@ -2803,7 +2826,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,


	smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
			    oparms->fid->lease_key, oplock, buf);
			    oparms->fid->lease_key, oplock, buf, posix);
creat_exit:
	SMB2_open_free(&rqst);
	free_rsp_buf(resp_buftype, rsp);
@@ -4302,7 +4325,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
	return rc;
}

static int posix_info_sid_size(const void *beg, const void *end)
int posix_info_sid_size(const void *beg, const void *end)
{
	size_t subauth;
	int total;
+5 −7
Original line number Diff line number Diff line
@@ -1605,13 +1605,11 @@ extern char smb2_padding[7];

/* equivalent of the contents of SMB3.1.1 POSIX open context response */
struct create_posix_rsp {
	__le32 nlink;
	__le32 reparse_tag;
	__le32 mode;
	/*
	 * var sized owner SID
	 * var sized group SID
	 */
	u32 nlink;
	u32 reparse_tag;
	u32 mode;
	struct cifs_sid owner; /* var-sized on the wire */
	struct cifs_sid group; /* var-sized on the wire */
} __packed;

/*
Loading