mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 22:02:28 +00:00
12 cifs/smb3 fixes, 2 for stable. Adds support for idsfromsid on create and chgrp/chown. Improves query info (getattr) when posix extensions negotiated.
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAl7kX6EACgkQiiy9cAdy T1GdiQwAqMaDRVLZWeV5Uc0EM9AGkrWVu6F5n9nBzuKDTXCAf8aKCyiyYdMz/P20 belQA3bPG4jkLa/4Or1XfTY2OSSV4eGBlTfjHNeW2ZJ5pJWGInqCHuVco/M98om8 57JMTMZDTxN6884U+v3bBl4jDE6MqK3QS0WfA63ufd0T8ZnFOGDBn1DieJKbViyy ZckpDH0etaAxO171SV5VwzbFe9U7OeTXupD8LYEHngR7vfaFCkX6ZftYYN0aWsvs uL3p6K1kiNNxTXm0M3Hw6Gpk1nEAM9/6nOR6+TUppor+rQVJCH5F7NKQVrR92MDq Qgwldt16DP1NjOb0q5L37HIg+9kD2kshKs9CErneen6eWtcfiN0HYT35hBxVi7RT XT/dMt17wq3waoq92+RY3U4vb47QVWS6asH4/sqsTqUMWrlEYNGkEuCfeniZzJfO bxglNPVafQ5qy2DWBzsAUX/isaR06FihEKqODK+K78KGTptim/+ip9+yXGjM6ne2 lhdWspC5 =Iwqj -----END PGP SIGNATURE----- Merge tag '5.8-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6 Pull more cifs updates from Steve French: "12 cifs/smb3 fixes, 2 for stable. - add support for idsfromsid on create and chgrp/chown allowing ability to save owner information more naturally for some workloads - improve query info (getattr) when SMB3.1.1 posix extensions are negotiated by using new query info level" * tag '5.8-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6: smb3: Add debug message for new file creation with idsfromsid mount option cifs: fix chown and chgrp when idsfromsid mount option enabled smb3: allow uid and gid owners to be set on create with idsfromsid mount option smb311: Add tracepoints for new compound posix query info smb311: add support for using info level for posix extensions query smb311: Add support for lookup with posix extensions query info smb311: Add support for SMB311 query info (non-compounded) SMB311: Add support for query info using posix extensions (level 100) smb3: add indatalen that can be a non-zero value to calculation of credit charge in smb2 ioctl smb3: fix typo in mount options displayed in /proc/mounts cifs: Add get_security_type_str function to return sec type. smb3: extend fscache mount volume coherency check
This commit is contained in:
commit
f82e7b57b5
@ -53,13 +53,6 @@ const struct fscache_cookie_def cifs_fscache_server_index_def = {
|
||||
.type = FSCACHE_COOKIE_TYPE_INDEX,
|
||||
};
|
||||
|
||||
/*
|
||||
* Auxiliary data attached to CIFS superblock within the cache
|
||||
*/
|
||||
struct cifs_fscache_super_auxdata {
|
||||
u64 resource_id; /* unique server resource id */
|
||||
};
|
||||
|
||||
char *extract_sharename(const char *treename)
|
||||
{
|
||||
const char *src;
|
||||
@ -98,6 +91,8 @@ fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data,
|
||||
|
||||
memset(&auxdata, 0, sizeof(auxdata));
|
||||
auxdata.resource_id = tcon->resource_id;
|
||||
auxdata.vol_create_time = tcon->vol_create_time;
|
||||
auxdata.vol_serial_number = tcon->vol_serial_number;
|
||||
|
||||
if (memcmp(data, &auxdata, datalen) != 0)
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
|
@ -221,8 +221,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||
struct cifs_ses *ses;
|
||||
struct cifs_tcon *tcon;
|
||||
int i, j;
|
||||
const char *security_types[] = {"Unspecified", "LANMAN", "NTLM",
|
||||
"NTLMv2", "RawNTLMSSP", "Kerberos"};
|
||||
|
||||
seq_puts(m,
|
||||
"Display Internal CIFS Data Structures for Debugging\n"
|
||||
@ -379,7 +377,7 @@ skip_rdma:
|
||||
}
|
||||
|
||||
seq_printf(m,"Security type: %s\n",
|
||||
security_types[server->ops->select_sectype(server, ses->sectype)]);
|
||||
get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
|
||||
|
||||
if (server->rdma)
|
||||
seq_printf(m, "RDMA\n\t");
|
||||
|
@ -849,6 +849,28 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
|
||||
return ace_size;
|
||||
}
|
||||
|
||||
unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
|
||||
{
|
||||
int i;
|
||||
unsigned int ace_size = 28;
|
||||
|
||||
pntace->type = ACCESS_ALLOWED_ACE_TYPE;
|
||||
pntace->flags = 0x0;
|
||||
pntace->access_req = cpu_to_le32(GENERIC_ALL);
|
||||
pntace->sid.num_subauth = 3;
|
||||
pntace->sid.revision = 1;
|
||||
for (i = 0; i < NUM_AUTHS; i++)
|
||||
pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
|
||||
|
||||
pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
|
||||
pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
|
||||
pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
|
||||
|
||||
/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
|
||||
pntace->size = cpu_to_le16(ace_size);
|
||||
return ace_size;
|
||||
}
|
||||
|
||||
static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
|
||||
struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
|
||||
{
|
||||
@ -978,7 +1000,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
|
||||
/* Convert permission bits from mode to equivalent CIFS ACL */
|
||||
static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
|
||||
bool mode_from_sid, int *aclflag)
|
||||
bool mode_from_sid, bool id_from_sid, int *aclflag)
|
||||
{
|
||||
int rc = 0;
|
||||
__u32 dacloffset;
|
||||
@ -1019,12 +1041,23 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
if (!nowner_sid_ptr)
|
||||
return -ENOMEM;
|
||||
id = from_kuid(&init_user_ns, uid);
|
||||
rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
|
||||
__func__, rc, id);
|
||||
kfree(nowner_sid_ptr);
|
||||
return rc;
|
||||
if (id_from_sid) {
|
||||
struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
|
||||
/* Populate the user ownership fields S-1-5-88-1 */
|
||||
osid->Revision = 1;
|
||||
osid->NumAuth = 3;
|
||||
osid->Authority[5] = 5;
|
||||
osid->SubAuthorities[0] = cpu_to_le32(88);
|
||||
osid->SubAuthorities[1] = cpu_to_le32(1);
|
||||
osid->SubAuthorities[2] = cpu_to_le32(id);
|
||||
} else { /* lookup sid with upcall */
|
||||
rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
|
||||
__func__, rc, id);
|
||||
kfree(nowner_sid_ptr);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
|
||||
kfree(nowner_sid_ptr);
|
||||
@ -1039,12 +1072,23 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
if (!ngroup_sid_ptr)
|
||||
return -ENOMEM;
|
||||
id = from_kgid(&init_user_ns, gid);
|
||||
rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
|
||||
__func__, rc, id);
|
||||
kfree(ngroup_sid_ptr);
|
||||
return rc;
|
||||
if (id_from_sid) {
|
||||
struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
|
||||
/* Populate the group ownership fields S-1-5-88-2 */
|
||||
gsid->Revision = 1;
|
||||
gsid->NumAuth = 3;
|
||||
gsid->Authority[5] = 5;
|
||||
gsid->SubAuthorities[0] = cpu_to_le32(88);
|
||||
gsid->SubAuthorities[1] = cpu_to_le32(2);
|
||||
gsid->SubAuthorities[2] = cpu_to_le32(id);
|
||||
} else { /* lookup sid with upcall */
|
||||
rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
|
||||
if (rc) {
|
||||
cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
|
||||
__func__, rc, id);
|
||||
kfree(ngroup_sid_ptr);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
|
||||
kfree(ngroup_sid_ptr);
|
||||
@ -1247,7 +1291,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||
struct smb_version_operations *ops;
|
||||
bool mode_from_sid;
|
||||
bool mode_from_sid, id_from_sid;
|
||||
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
@ -1290,8 +1334,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
|
||||
else
|
||||
mode_from_sid = false;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
|
||||
id_from_sid = true;
|
||||
else
|
||||
id_from_sid = false;
|
||||
|
||||
rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
|
||||
mode_from_sid, &aclflag);
|
||||
mode_from_sid, id_from_sid, &aclflag);
|
||||
|
||||
cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
|
||||
|
||||
|
@ -176,6 +176,21 @@ struct smb3_acl {
|
||||
__le16 Sbz2; /* MBZ */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid
|
||||
* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
|
||||
*/
|
||||
struct owner_sid {
|
||||
u8 Revision;
|
||||
u8 NumAuth;
|
||||
u8 Authority[6];
|
||||
__le32 SubAuthorities[3];
|
||||
} __packed;
|
||||
|
||||
struct owner_group_sids {
|
||||
struct owner_sid owner;
|
||||
struct owner_sid group;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Minimum security identifier can be one for system defined Users
|
||||
|
@ -623,7 +623,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
|
||||
|
||||
if (tcon->ses->chan_max > 1)
|
||||
seq_printf(s, ",multichannel,max_channel=%zu",
|
||||
seq_printf(s, ",multichannel,max_channels=%zu",
|
||||
tcon->ses->chan_max);
|
||||
|
||||
return 0;
|
||||
|
@ -2008,6 +2008,24 @@ extern struct smb_version_values smb302_values;
|
||||
extern struct smb_version_operations smb311_operations;
|
||||
extern struct smb_version_values smb311_values;
|
||||
|
||||
static inline char *get_security_type_str(enum securityEnum sectype)
|
||||
{
|
||||
switch (sectype) {
|
||||
case RawNTLMSSP:
|
||||
return "RawNTLMSSP";
|
||||
case Kerberos:
|
||||
return "Kerberos";
|
||||
case NTLMv2:
|
||||
return "NTLMv2";
|
||||
case NTLM:
|
||||
return "NTLM";
|
||||
case LANMAN:
|
||||
return "LANMAN";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_smb1_server(struct TCP_Server_Info *server)
|
||||
{
|
||||
return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;
|
||||
|
@ -198,6 +198,8 @@ extern struct inode *cifs_iget(struct super_block *sb,
|
||||
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||
FILE_ALL_INFO *data, struct super_block *sb,
|
||||
int xid, const struct cifs_fid *fid);
|
||||
extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
|
||||
struct super_block *sb, unsigned int xid);
|
||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
struct super_block *sb, unsigned int xid);
|
||||
@ -220,6 +222,7 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
|
||||
const char *, int);
|
||||
extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
|
||||
extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
|
||||
extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
|
||||
|
||||
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
|
||||
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
|
||||
|
@ -411,6 +411,7 @@ cifs_create_get_file_info:
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
|
||||
xid);
|
||||
else {
|
||||
/* TODO: Add support for calling POSIX query info here, but passing in fid */
|
||||
rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
|
||||
xid, fid);
|
||||
if (newinode) {
|
||||
@ -700,7 +701,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
|
||||
full_path, d_inode(direntry));
|
||||
|
||||
if (pTcon->unix_ext) {
|
||||
if (pTcon->posix_extensions)
|
||||
rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
|
||||
else if (pTcon->unix_ext) {
|
||||
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
||||
parent_dir_inode->i_sb, xid);
|
||||
} else {
|
||||
|
@ -243,6 +243,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/* TODO: Add support for calling posix query info but with passing in fid */
|
||||
if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
|
||||
xid);
|
||||
@ -800,7 +801,9 @@ reopen_success:
|
||||
if (!is_interrupt_error(rc))
|
||||
mapping_set_error(inode->i_mapping, rc);
|
||||
|
||||
if (tcon->unix_ext)
|
||||
if (tcon->posix_extensions)
|
||||
rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
|
||||
else if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path,
|
||||
inode->i_sb, xid);
|
||||
else
|
||||
|
@ -96,6 +96,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
||||
{
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
char *sharename;
|
||||
struct cifs_fscache_super_auxdata auxdata;
|
||||
|
||||
sharename = extract_sharename(tcon->treeName);
|
||||
if (IS_ERR(sharename)) {
|
||||
@ -104,11 +105,16 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&auxdata, 0, sizeof(auxdata));
|
||||
auxdata.resource_id = tcon->resource_id;
|
||||
auxdata.vol_create_time = tcon->vol_create_time;
|
||||
auxdata.vol_serial_number = tcon->vol_serial_number;
|
||||
|
||||
tcon->fscache =
|
||||
fscache_acquire_cookie(server->fscache,
|
||||
&cifs_fscache_super_index_def,
|
||||
sharename, strlen(sharename),
|
||||
&tcon->resource_id, sizeof(tcon->resource_id),
|
||||
&auxdata, sizeof(auxdata),
|
||||
tcon, 0, true);
|
||||
kfree(sharename);
|
||||
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
|
||||
@ -117,8 +123,15 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
||||
|
||||
void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
|
||||
{
|
||||
struct cifs_fscache_super_auxdata auxdata;
|
||||
|
||||
memset(&auxdata, 0, sizeof(auxdata));
|
||||
auxdata.resource_id = tcon->resource_id;
|
||||
auxdata.vol_create_time = tcon->vol_create_time;
|
||||
auxdata.vol_serial_number = tcon->vol_serial_number;
|
||||
|
||||
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
|
||||
fscache_relinquish_cookie(tcon->fscache, &tcon->resource_id, false);
|
||||
fscache_relinquish_cookie(tcon->fscache, &auxdata, false);
|
||||
tcon->fscache = NULL;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,15 @@
|
||||
|
||||
#ifdef CONFIG_CIFS_FSCACHE
|
||||
|
||||
/*
|
||||
* Auxiliary data attached to CIFS superblock within the cache
|
||||
*/
|
||||
struct cifs_fscache_super_auxdata {
|
||||
u64 resource_id; /* unique server resource id */
|
||||
__le64 vol_create_time;
|
||||
u32 vol_serial_number;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Auxiliary data attached to CIFS inode within the cache
|
||||
*/
|
||||
|
185
fs/cifs/inode.c
185
fs/cifs/inode.c
@ -32,6 +32,7 @@
|
||||
#include "cifspdu.h"
|
||||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "smb2proto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifs_fs_sb.h"
|
||||
#include "cifs_unicode.h"
|
||||
@ -595,6 +596,62 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Fill a cifs_fattr struct with info from POSIX info struct */
|
||||
static void
|
||||
smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *info,
|
||||
struct super_block *sb, bool adjust_tz, bool symlink)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
memset(fattr, 0, sizeof(*fattr));
|
||||
|
||||
/* no fattr->flags to set */
|
||||
fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
|
||||
fattr->cf_uniqueid = le64_to_cpu(info->Inode);
|
||||
|
||||
if (info->LastAccessTime)
|
||||
fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
|
||||
else
|
||||
ktime_get_coarse_real_ts64(&fattr->cf_atime);
|
||||
|
||||
fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
|
||||
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
|
||||
|
||||
if (adjust_tz) {
|
||||
fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
|
||||
fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
|
||||
}
|
||||
|
||||
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
|
||||
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
|
||||
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
|
||||
|
||||
fattr->cf_nlink = le32_to_cpu(info->HardLinks);
|
||||
fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
|
||||
/* The srv fs device id is overridden on network mount so setting rdev isn't needed here */
|
||||
/* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */
|
||||
|
||||
if (symlink) {
|
||||
fattr->cf_mode |= S_IFLNK;
|
||||
fattr->cf_dtype = DT_LNK;
|
||||
} else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
|
||||
fattr->cf_mode |= S_IFDIR;
|
||||
fattr->cf_dtype = DT_DIR;
|
||||
} else { /* file */
|
||||
fattr->cf_mode |= S_IFREG;
|
||||
fattr->cf_dtype = DT_REG;
|
||||
}
|
||||
/* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
|
||||
|
||||
fattr->cf_uid = cifs_sb->mnt_uid; /* TODO: map uid and gid from SID */
|
||||
fattr->cf_gid = cifs_sb->mnt_gid;
|
||||
|
||||
cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
|
||||
fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
|
||||
}
|
||||
|
||||
|
||||
/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
|
||||
static void
|
||||
cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
|
||||
@ -1023,6 +1080,121 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
smb311_posix_get_inode_info(struct inode **inode,
|
||||
const char *full_path,
|
||||
struct super_block *sb, unsigned int xid)
|
||||
{
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
bool adjust_tz = false;
|
||||
struct cifs_fattr fattr = {0};
|
||||
bool symlink = false;
|
||||
struct smb311_posix_qinfo *data = NULL;
|
||||
int rc = 0;
|
||||
int tmprc = 0;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
server = tcon->ses->server;
|
||||
|
||||
/*
|
||||
* 1. Fetch file metadata
|
||||
*/
|
||||
|
||||
if (is_inode_cache_good(*inode)) {
|
||||
cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
|
||||
goto out;
|
||||
}
|
||||
data = kmalloc(sizeof(struct smb311_posix_qinfo), GFP_KERNEL);
|
||||
if (!data) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
|
||||
full_path, data,
|
||||
&adjust_tz, &symlink);
|
||||
|
||||
/*
|
||||
* 2. Convert it to internal cifs metadata (fattr)
|
||||
*/
|
||||
|
||||
switch (rc) {
|
||||
case 0:
|
||||
smb311_posix_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
|
||||
break;
|
||||
case -EREMOTE:
|
||||
/* DFS link, no metadata available on this server */
|
||||
cifs_create_dfs_fattr(&fattr, sb);
|
||||
rc = 0;
|
||||
break;
|
||||
case -EACCES:
|
||||
/*
|
||||
* For SMB2 and later the backup intent flag
|
||||
* is already sent if needed on open and there
|
||||
* is no path based FindFirst operation to use
|
||||
* to retry with so nothing we can do, bail out
|
||||
*/
|
||||
goto out;
|
||||
default:
|
||||
cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 3. Tweak fattr based on mount options
|
||||
*/
|
||||
|
||||
/* check for Minshall+French symlinks */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||
tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
|
||||
full_path);
|
||||
if (tmprc)
|
||||
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
|
||||
}
|
||||
|
||||
/*
|
||||
* 4. Update inode with final fattr data
|
||||
*/
|
||||
|
||||
if (!*inode) {
|
||||
*inode = cifs_iget(sb, &fattr);
|
||||
if (!*inode)
|
||||
rc = -ENOMEM;
|
||||
} else {
|
||||
/* we already have inode, update it */
|
||||
|
||||
/* if uniqueid is different, return error */
|
||||
if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
|
||||
CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
|
||||
CIFS_I(*inode)->time = 0; /* force reval */
|
||||
rc = -ESTALE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if filetype is different, return error */
|
||||
if (unlikely(((*inode)->i_mode & S_IFMT) !=
|
||||
(fattr.cf_mode & S_IFMT))) {
|
||||
CIFS_I(*inode)->time = 0; /* force reval */
|
||||
rc = -ESTALE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cifs_fattr_to_inode(*inode, &fattr);
|
||||
}
|
||||
out:
|
||||
cifs_put_tlink(tlink);
|
||||
kfree(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static const struct inode_operations cifs_ipc_inode_ops = {
|
||||
.lookup = cifs_lookup,
|
||||
};
|
||||
@ -1161,7 +1333,10 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
||||
}
|
||||
|
||||
convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
|
||||
rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
|
||||
if (tcon->posix_extensions)
|
||||
rc = smb311_posix_get_inode_info(&inode, path, sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
|
||||
|
||||
iget_no_retry:
|
||||
if (!inode) {
|
||||
@ -1517,7 +1692,9 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
|
||||
int rc = 0;
|
||||
struct inode *inode = NULL;
|
||||
|
||||
if (tcon->unix_ext)
|
||||
if (tcon->posix_extensions)
|
||||
rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid);
|
||||
else if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb,
|
||||
xid);
|
||||
else
|
||||
@ -2114,7 +2291,9 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
|
||||
dentry, cifs_get_time(dentry), jiffies);
|
||||
|
||||
again:
|
||||
if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
|
||||
if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions)
|
||||
rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid);
|
||||
else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
|
||||
|
@ -701,7 +701,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||
cifs_sb_target->local_nls); */
|
||||
|
||||
if (rc == 0) {
|
||||
if (pTcon->unix_ext)
|
||||
if (pTcon->posix_extensions)
|
||||
rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid);
|
||||
else if (pTcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||
inode->i_sb, xid);
|
||||
else
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define SMB2_OP_HARDLINK 8
|
||||
#define SMB2_OP_SET_EOF 9
|
||||
#define SMB2_OP_RMDIR 10
|
||||
#define SMB2_OP_POSIX_QUERY_INFO 11
|
||||
|
||||
/* Used when constructing chained read requests. */
|
||||
#define CHAINED_REQUEST 1
|
||||
|
@ -166,6 +166,40 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
|
||||
full_path);
|
||||
break;
|
||||
case SMB2_OP_POSIX_QUERY_INFO:
|
||||
rqst[num_rqst].rq_iov = &vars->qi_iov[0];
|
||||
rqst[num_rqst].rq_nvec = 1;
|
||||
|
||||
if (cfile)
|
||||
rc = SMB2_query_info_init(tcon, server,
|
||||
&rqst[num_rqst],
|
||||
cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid,
|
||||
SMB_FIND_FILE_POSIX_INFO,
|
||||
SMB2_O_INFO_FILE, 0,
|
||||
/* TBD: fix following to allow for longer SIDs */
|
||||
sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
|
||||
(sizeof(struct cifs_sid) * 2), 0, NULL);
|
||||
else {
|
||||
rc = SMB2_query_info_init(tcon, server,
|
||||
&rqst[num_rqst],
|
||||
COMPOUND_FID,
|
||||
COMPOUND_FID,
|
||||
SMB_FIND_FILE_POSIX_INFO,
|
||||
SMB2_O_INFO_FILE, 0,
|
||||
sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) +
|
||||
(sizeof(struct cifs_sid) * 2), 0, NULL);
|
||||
if (!rc) {
|
||||
smb2_set_next_command(tcon, &rqst[num_rqst]);
|
||||
smb2_set_related(&rqst[num_rqst]);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc)
|
||||
goto finished;
|
||||
num_rqst++;
|
||||
trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path);
|
||||
break;
|
||||
case SMB2_OP_DELETE:
|
||||
trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path);
|
||||
break;
|
||||
@ -379,6 +413,24 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
trace_smb3_query_info_compound_done(xid, ses->Suid,
|
||||
tcon->tid);
|
||||
break;
|
||||
case SMB2_OP_POSIX_QUERY_INFO:
|
||||
if (rc == 0) {
|
||||
qi_rsp = (struct smb2_query_info_rsp *)
|
||||
rsp_iov[1].iov_base;
|
||||
rc = smb2_validate_and_copy_iov(
|
||||
le16_to_cpu(qi_rsp->OutputBufferOffset),
|
||||
le32_to_cpu(qi_rsp->OutputBufferLength),
|
||||
&rsp_iov[1], sizeof(struct smb311_posix_qinfo) /* add SIDs */, ptr);
|
||||
}
|
||||
if (rqst[1].rq_iov)
|
||||
SMB2_query_info_free(&rqst[1]);
|
||||
if (rqst[2].rq_iov)
|
||||
SMB2_close_free(&rqst[2]);
|
||||
if (rc)
|
||||
trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc);
|
||||
else
|
||||
trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid);
|
||||
break;
|
||||
case SMB2_OP_DELETE:
|
||||
if (rc)
|
||||
trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc);
|
||||
@ -512,6 +564,59 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
struct smb311_posix_qinfo *data, bool *adjust_tz, bool *symlink)
|
||||
{
|
||||
int rc;
|
||||
__u32 create_options = 0;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct smb311_posix_qinfo *smb2_data;
|
||||
|
||||
*adjust_tz = false;
|
||||
*symlink = false;
|
||||
|
||||
/* BB TODO: Make struct larger when add support for parsing owner SIDs */
|
||||
smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo),
|
||||
GFP_KERNEL);
|
||||
if (smb2_data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* BB TODO: Add support for using the cached root handle.
|
||||
* Create SMB2_query_posix_info worker function to do non-compounded query
|
||||
* when we already have an open file handle for this. For now this is fast enough
|
||||
* (always using the compounded version).
|
||||
*/
|
||||
|
||||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
|
||||
ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
/* BB TODO: When support for special files added to Samba re-verify this path */
|
||||
*symlink = true;
|
||||
create_options |= OPEN_REPARSE_POINT;
|
||||
|
||||
/* Failed on a symbolic link - query a reparse point info */
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
|
||||
FILE_READ_ATTRIBUTES, FILE_OPEN,
|
||||
create_options, ACL_NO_MODE,
|
||||
smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL);
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/* TODO: will need to allow for the 2 SIDs when add support for getting owner UID/GID */
|
||||
memcpy(data, smb2_data, sizeof(struct smb311_posix_qinfo));
|
||||
|
||||
out:
|
||||
kfree(smb2_data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
|
||||
struct cifs_tcon *tcon, const char *name,
|
||||
|
@ -2317,28 +2317,75 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
|
||||
static void setup_owner_group_sids(char *buf)
|
||||
{
|
||||
struct owner_group_sids *sids = (struct owner_group_sids *)buf;
|
||||
|
||||
/* Populate the user ownership fields S-1-5-88-1 */
|
||||
sids->owner.Revision = 1;
|
||||
sids->owner.NumAuth = 3;
|
||||
sids->owner.Authority[5] = 5;
|
||||
sids->owner.SubAuthorities[0] = cpu_to_le32(88);
|
||||
sids->owner.SubAuthorities[1] = cpu_to_le32(1);
|
||||
sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val);
|
||||
|
||||
/* Populate the group ownership fields S-1-5-88-2 */
|
||||
sids->group.Revision = 1;
|
||||
sids->group.NumAuth = 3;
|
||||
sids->group.Authority[5] = 5;
|
||||
sids->group.SubAuthorities[0] = cpu_to_le32(88);
|
||||
sids->group.SubAuthorities[1] = cpu_to_le32(2);
|
||||
sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val);
|
||||
|
||||
cifs_dbg(FYI, "owner S-1-5-88-1-%d, group S-1-5-88-2-%d\n", current_fsuid().val, current_fsgid().val);
|
||||
}
|
||||
|
||||
/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
|
||||
static struct crt_sd_ctxt *
|
||||
create_sd_buf(umode_t mode, unsigned int *len)
|
||||
create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
|
||||
{
|
||||
struct crt_sd_ctxt *buf;
|
||||
struct cifs_ace *pace;
|
||||
unsigned int sdlen, acelen;
|
||||
unsigned int owner_offset = 0;
|
||||
unsigned int group_offset = 0;
|
||||
|
||||
*len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 2), 8);
|
||||
|
||||
if (set_owner) {
|
||||
/* offset fields are from beginning of security descriptor not of create context */
|
||||
owner_offset = sizeof(struct smb3_acl) + (sizeof(struct cifs_ace) * 2);
|
||||
|
||||
/* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
|
||||
*len += sizeof(struct owner_group_sids);
|
||||
}
|
||||
|
||||
*len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2,
|
||||
8);
|
||||
buf = kzalloc(*len, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return buf;
|
||||
|
||||
if (set_owner) {
|
||||
buf->sd.OffsetOwner = cpu_to_le32(owner_offset);
|
||||
group_offset = owner_offset + sizeof(struct owner_sid);
|
||||
buf->sd.OffsetGroup = cpu_to_le32(group_offset);
|
||||
} else {
|
||||
buf->sd.OffsetOwner = 0;
|
||||
buf->sd.OffsetGroup = 0;
|
||||
}
|
||||
|
||||
sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) +
|
||||
2 * sizeof(struct cifs_ace);
|
||||
if (set_owner) {
|
||||
sdlen += sizeof(struct owner_group_sids);
|
||||
setup_owner_group_sids(owner_offset + sizeof(struct create_context) + 8 /* name */
|
||||
+ (char *)buf);
|
||||
}
|
||||
|
||||
buf->ccontext.DataOffset = cpu_to_le16(offsetof
|
||||
(struct crt_sd_ctxt, sd));
|
||||
buf->ccontext.DataLength = cpu_to_le32(sdlen);
|
||||
buf->ccontext.NameOffset = cpu_to_le16(offsetof
|
||||
(struct crt_sd_ctxt, Name));
|
||||
buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
|
||||
buf->ccontext.NameLength = cpu_to_le16(4);
|
||||
/* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
|
||||
buf->Name[0] = 'S';
|
||||
@ -2359,23 +2406,34 @@ create_sd_buf(umode_t mode, unsigned int *len)
|
||||
/* create one ACE to hold the mode embedded in reserved special SID */
|
||||
pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf);
|
||||
acelen = setup_special_mode_ACE(pace, (__u64)mode);
|
||||
|
||||
if (set_owner) {
|
||||
/* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
|
||||
pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf));
|
||||
acelen += setup_special_user_owner_ACE(pace);
|
||||
/* it does not appear necessary to add an ACE for the NFS group SID */
|
||||
buf->acl.AceCount = cpu_to_le16(3);
|
||||
} else
|
||||
buf->acl.AceCount = cpu_to_le16(2);
|
||||
|
||||
/* and one more ACE to allow access for authenticated users */
|
||||
pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) +
|
||||
(char *)buf));
|
||||
acelen += setup_authusers_ACE(pace);
|
||||
|
||||
buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen);
|
||||
buf->acl.AceCount = cpu_to_le16(2);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
|
||||
add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
|
||||
{
|
||||
struct smb2_create_req *req = iov[0].iov_base;
|
||||
unsigned int num = *num_iovec;
|
||||
unsigned int len = 0;
|
||||
|
||||
iov[num].iov_base = create_sd_buf(mode, &len);
|
||||
iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
|
||||
if (iov[num].iov_base == NULL)
|
||||
return -ENOMEM;
|
||||
iov[num].iov_len = len;
|
||||
@ -2764,21 +2822,35 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((oparms->disposition != FILE_OPEN) &&
|
||||
(oparms->cifs_sb) &&
|
||||
(oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
|
||||
(oparms->mode != ACL_NO_MODE)) {
|
||||
if (n_iov > 2) {
|
||||
struct create_context *ccontext =
|
||||
(struct create_context *)iov[n_iov-1].iov_base;
|
||||
ccontext->Next =
|
||||
cpu_to_le32(iov[n_iov-1].iov_len);
|
||||
if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
|
||||
bool set_mode;
|
||||
bool set_owner;
|
||||
|
||||
if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
|
||||
(oparms->mode != ACL_NO_MODE))
|
||||
set_mode = true;
|
||||
else {
|
||||
set_mode = false;
|
||||
oparms->mode = ACL_NO_MODE;
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
|
||||
rc = add_sd_context(iov, &n_iov, oparms->mode);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
|
||||
set_owner = true;
|
||||
else
|
||||
set_owner = false;
|
||||
|
||||
if (set_owner | set_mode) {
|
||||
if (n_iov > 2) {
|
||||
struct create_context *ccontext =
|
||||
(struct create_context *)iov[n_iov-1].iov_base;
|
||||
ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
|
||||
rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_iov > 2) {
|
||||
@ -2973,7 +3045,9 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
|
||||
* response size smaller.
|
||||
*/
|
||||
req->MaxOutputResponse = cpu_to_le32(max_response_size);
|
||||
req->sync_hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(max_response_size, SMB2_MAX_BUFFER_SIZE));
|
||||
req->sync_hdr.CreditCharge =
|
||||
cpu_to_le16(DIV_ROUND_UP(max(indatalen, max_response_size),
|
||||
SMB2_MAX_BUFFER_SIZE));
|
||||
if (is_fsctl)
|
||||
req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL);
|
||||
else
|
||||
@ -3456,6 +3530,19 @@ int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int
|
||||
SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
|
||||
{
|
||||
size_t output_len = sizeof(struct smb311_posix_qinfo *) +
|
||||
(sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2);
|
||||
*plen = 0;
|
||||
|
||||
return query_info(xid, tcon, persistent_fid, volatile_fid,
|
||||
SMB_FIND_FILE_POSIX_INFO, SMB2_O_INFO_FILE, 0,
|
||||
output_len, sizeof(struct smb311_posix_qinfo), (void **)&data, plen);
|
||||
}
|
||||
|
||||
int
|
||||
SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid,
|
||||
|
@ -1653,7 +1653,7 @@ struct create_posix_rsp {
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* SMB2-only POSIX info level
|
||||
* SMB2-only POSIX info level for query dir
|
||||
*
|
||||
* See posix_info_sid_size(), posix_info_extra_size() and
|
||||
* posix_info_parse() to help with the handling of this struct.
|
||||
@ -1683,6 +1683,31 @@ struct smb2_posix_info {
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/* Level 100 query info */
|
||||
struct smb311_posix_qinfo {
|
||||
__le64 CreationTime;
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le64 EndOfFile;
|
||||
__le64 AllocationSize;
|
||||
__le32 DosAttributes;
|
||||
__le64 Inode;
|
||||
__le32 DeviceId;
|
||||
__le32 Zero;
|
||||
/* beginning of POSIX Create Context Response */
|
||||
__le32 HardLinks;
|
||||
__le32 ReparseTag;
|
||||
__le32 Mode;
|
||||
u8 Sids[];
|
||||
/*
|
||||
* var sized owner SID
|
||||
* var sized group SID
|
||||
* le32 filenamelength
|
||||
* u8 filename[]
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Parsed version of the above struct. Allows direct access to the
|
||||
* variable length fields
|
||||
|
@ -182,6 +182,8 @@ extern int SMB2_flush_init(const unsigned int xid, struct smb_rqst *rqst,
|
||||
struct TCP_Server_Info *server,
|
||||
u64 persistent_file_id, u64 volatile_file_id);
|
||||
extern void SMB2_flush_free(struct smb_rqst *rqst);
|
||||
extern int SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen);
|
||||
extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_file_id, u64 volatile_file_id,
|
||||
struct smb2_file_all_info *data);
|
||||
@ -289,6 +291,10 @@ extern int smb2_query_info_compound(const unsigned int xid,
|
||||
u32 class, u32 type, u32 output_len,
|
||||
struct kvec *rsp, int *buftype,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
/* query path info from the server using SMB311 POSIX extensions*/
|
||||
extern int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *sb, const char *path, struct smb311_posix_qinfo *qinf,
|
||||
bool *adjust_tx, bool *symlink);
|
||||
int posix_info_parse(const void *beg, const void *end,
|
||||
struct smb2_posix_info_parsed *out);
|
||||
int posix_info_sid_size(const void *beg, const void *end);
|
||||
|
@ -318,6 +318,7 @@ DEFINE_EVENT(smb3_inf_compound_enter_class, smb3_##name, \
|
||||
TP_ARGS(xid, tid, sesid, full_path))
|
||||
|
||||
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter);
|
||||
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter);
|
||||
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter);
|
||||
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter);
|
||||
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter);
|
||||
@ -354,6 +355,7 @@ DEFINE_EVENT(smb3_inf_compound_done_class, smb3_##name, \
|
||||
TP_ARGS(xid, tid, sesid))
|
||||
|
||||
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done);
|
||||
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done);
|
||||
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done);
|
||||
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done);
|
||||
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done);
|
||||
@ -395,6 +397,7 @@ DEFINE_EVENT(smb3_inf_compound_err_class, smb3_##name, \
|
||||
TP_ARGS(xid, tid, sesid, rc))
|
||||
|
||||
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err);
|
||||
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err);
|
||||
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err);
|
||||
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err);
|
||||
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err);
|
||||
|
Loading…
Reference in New Issue
Block a user