24 smb3 client fixes, about half cleanup, and SMB3.1.1 compression improvements, and also fixes for special file types with sfu mount option

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmbpAwkACgkQiiy9cAdy
 T1FJhgv+PX+IIGyNNW0I3f3ZzIWqc1DCwxXHCa3gvr7TKimJ71AGbEdzFZZzl3AJ
 CdxSLf2NQ6tBUxl65QuMC7XykqQXKvNnQEDPoQcHfFgTtYJi+zng1dDvvXSfFbWW
 m2Hql1w6MNFeKlFBavbA6MI94MnZqE5J/yCtWqw3LvEn4l2JwYrAzS5Lw9qjtcER
 DmlOsrEFgpsFhhpnyPZXJxaWKZIDG2OuG61LWkqyhvLOTtuFuc9cEsTWPdeRYAT6
 KKh5z58wqG2JG0IkVjG1foBclv0zcZgUzqOr2/tzbabYye991kLnUitaTwd+u8xS
 pTbVIw1E91sFEqVsr2IpnLUq68MKaahlNfHkNJD0dqaMKfGOujqtNRFw82Yki4w5
 aTosgECyUiGKgwuE8HLtwlJaE4EizVdrqQiP2cUOrtuWPvOvnY7vjWKC8kmSM0Z/
 u0ov6JdirVlnFE3dlS0i6ywKaolsrrPYUTbv4ihjQiGHtm+VjonH8VYsdg8sUV0e
 5/+cyqaF
 =B6Et
 -----END PGP SIGNATURE-----

Merge tag 'v6.12-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client updates from Steve French:

 - cleanups (moving duplicated code, removing unused code etc)

 - fixes relating to "sfu" mount options (for better handling special
   file types)

 - SMB3.1.1 compression fixes/improvements

* tag 'v6.12-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: (24 commits)
  smb: client: fix compression heuristic functions
  cifs: Update SFU comments about fifos and sockets
  cifs: Add support for creating SFU symlinks
  smb: use LIST_HEAD() to simplify code
  cifs: Recognize SFU socket type
  cifs: Show debug message when SFU Fifo type was detected
  cifs: Put explicit zero byte into SFU block/char types
  cifs: Add support for reading SFU symlink location
  cifs: Fix recognizing SFU symlinks
  smb: client: compress: fix an "illegal accesses" issue
  smb: client: compress: fix a potential issue of freeing an invalid pointer
  smb: client: compress: LZ77 code improvements cleanup
  smb: client: insert compression check/call on write requests
  smb3: mark compression as CONFIG_EXPERIMENTAL and fix missing compression operation
  cifs: Remove obsoleted declaration for cifs_dir_open
  smb: client: Use min() macro
  cifs: convert to use ERR_CAST()
  smb: add comment to STATUS_MCA_OCCURED
  smb: move SMB2 Status code to common header file
  smb: move some duplicate definitions to common/smbacl.h
  ...
This commit is contained in:
Linus Torvalds 2024-09-19 06:53:40 +02:00
commit 4e0373f1f9
43 changed files with 1206 additions and 2265 deletions

View File

@ -204,4 +204,18 @@ config CIFS_ROOT
Most people say N here.
config CIFS_COMPRESSION
bool "SMB message compression (Experimental)"
depends on CIFS
default n
help
Enables over-the-wire message compression for SMB 3.1.1
mounts when negotiated with the server.
Only write requests with data size >= PAGE_SIZE will be
compressed to avoid wasting resources.
Say Y here if you want SMB traffic to be compressed.
If unsure, say N.
endif

View File

@ -33,3 +33,5 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o
cifs-$(CONFIG_CIFS_COMPRESSION) += compress.o compress/lz77.o

View File

@ -349,6 +349,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
seq_printf(m, ",ACL");
#ifdef CONFIG_CIFS_SWN_UPCALL
seq_puts(m, ",WITNESS");
#endif
#ifdef CONFIG_CIFS_COMPRESSION
seq_puts(m, ",COMPRESSION");
#endif
seq_putc(m, '\n');
seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
@ -475,7 +478,9 @@ skip_rdma:
}
seq_puts(m, "\nCompression: ");
if (!server->compression.requested)
if (!IS_ENABLED(CONFIG_CIFS_COMPRESSION))
seq_puts(m, "no built-in support");
else if (!server->compression.requested)
seq_puts(m, "disabled on mount");
else if (server->compression.enabled)
seq_printf(m, "enabled (%s)", compression_alg_str(server->compression.alg));

View File

@ -27,18 +27,18 @@
#include "cifs_unicode.h"
/* security id for everyone/world system group */
static const struct cifs_sid sid_everyone = {
static const struct smb_sid sid_everyone = {
1, 1, {0, 0, 0, 0, 0, 1}, {0} };
/* security id for Authenticated Users system group */
static const struct cifs_sid sid_authusers = {
static const struct smb_sid sid_authusers = {
1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
/* S-1-22-1 Unmapped Unix users */
static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
static const struct smb_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
{cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
/* S-1-22-2 Unmapped Unix groups */
static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
static const struct smb_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
{cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
/*
@ -48,17 +48,17 @@ static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
/* S-1-5-88-1 Unix uid */
static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
static const struct smb_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
{cpu_to_le32(88),
cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
/* S-1-5-88-2 Unix gid */
static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
static const struct smb_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
{cpu_to_le32(88),
cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
/* S-1-5-88-3 Unix mode */
static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
static const struct smb_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
{cpu_to_le32(88),
cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
@ -106,7 +106,7 @@ static struct key_type cifs_idmap_key_type = {
};
static char *
sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
sid_to_key_str(struct smb_sid *sidptr, unsigned int type)
{
int i, len;
unsigned int saval;
@ -158,7 +158,7 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
* the same returns zero, if they do not match returns non-zero.
*/
static int
compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid)
{
int i;
int num_subauth, num_sat, num_saw;
@ -187,7 +187,7 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
/* compare all of the subauth values if any */
num_sat = ctsid->num_subauth;
num_saw = cwsid->num_subauth;
num_subauth = num_sat < num_saw ? num_sat : num_saw;
num_subauth = min(num_sat, num_saw);
if (num_subauth) {
for (i = 0; i < num_subauth; ++i) {
if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
@ -204,11 +204,11 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
}
static bool
is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
is_well_known_sid(const struct smb_sid *psid, uint32_t *puid, bool is_group)
{
int i;
int num_subauth;
const struct cifs_sid *pwell_known_sid;
const struct smb_sid *pwell_known_sid;
if (!psid || (puid == NULL))
return false;
@ -260,7 +260,7 @@ is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
}
static __u16
cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
cifs_copy_sid(struct smb_sid *dst, const struct smb_sid *src)
{
int i;
__u16 size = 1 + 1 + 6;
@ -277,11 +277,11 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
}
static int
id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
{
int rc;
struct key *sidkey;
struct cifs_sid *ksid;
struct smb_sid *ksid;
unsigned int ksid_size;
char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
const struct cred *saved_cred;
@ -312,8 +312,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
* it could be.
*/
ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
(struct cifs_sid *)&sidkey->payload :
(struct cifs_sid *)sidkey->payload.data[0];
(struct smb_sid *)&sidkey->payload :
(struct smb_sid *)sidkey->payload.data[0];
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
if (ksid_size > sidkey->datalen) {
@ -336,7 +336,7 @@ invalidate_key:
}
int
sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
struct cifs_fattr *fattr, uint sidtype)
{
int rc = 0;
@ -515,43 +515,43 @@ exit_cifs_idmap(void)
}
/* copy ntsd, owner sid, and group sid from a security descriptor to another */
static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
struct cifs_ntsd *pnntsd,
static __u32 copy_sec_desc(const struct smb_ntsd *pntsd,
struct smb_ntsd *pnntsd,
__u32 sidsoffset,
struct cifs_sid *pownersid,
struct cifs_sid *pgrpsid)
struct smb_sid *pownersid,
struct smb_sid *pgrpsid)
{
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr;
/* copy security descriptor control portion */
pnntsd->revision = pntsd->revision;
pnntsd->type = pntsd->type;
pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
pnntsd->dacloffset = cpu_to_le32(sizeof(struct smb_ntsd));
pnntsd->sacloffset = 0;
pnntsd->osidoffset = cpu_to_le32(sidsoffset);
pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct smb_sid));
/* copy owner sid */
if (pownersid)
owner_sid_ptr = pownersid;
else
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
nowner_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset);
cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
/* copy group sid */
if (pgrpsid)
group_sid_ptr = pgrpsid;
else
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
group_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
sizeof(struct cifs_sid));
ngroup_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset +
sizeof(struct smb_sid));
cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
return sidsoffset + (2 * sizeof(struct cifs_sid));
return sidsoffset + (2 * sizeof(struct smb_sid));
}
@ -666,7 +666,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
return;
}
static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid)
static __u16 cifs_copy_ace(struct smb_ace *dst, struct smb_ace *src, struct smb_sid *psid)
{
__u16 size = 1 + 1 + 2 + 4;
@ -685,8 +685,8 @@ static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct ci
return size;
}
static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
const struct cifs_sid *psid, __u64 nmode,
static __u16 fill_ace_for_sid(struct smb_ace *pntace,
const struct smb_sid *psid, __u64 nmode,
umode_t bits, __u8 access_type,
bool allow_delete_child)
{
@ -723,7 +723,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
#ifdef CONFIG_CIFS_DEBUG2
static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
static void dump_ace(struct smb_ace *pace, char *end_of_acl)
{
int num_subauth;
@ -758,15 +758,15 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
}
#endif
static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
struct cifs_fattr *fattr, bool mode_from_special_sid)
{
int i;
int num_aces = 0;
int acl_size;
char *acl_base;
struct cifs_ace **ppace;
struct smb_ace **ppace;
/* BB need to add parm so we can store the SID BB */
@ -793,21 +793,21 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
fattr->cf_mode &= ~(0777);
acl_base = (char *)pdacl;
acl_size = sizeof(struct cifs_acl);
acl_size = sizeof(struct smb_acl);
num_aces = le32_to_cpu(pdacl->num_aces);
if (num_aces > 0) {
umode_t denied_mode = 0;
if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
return;
ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *),
GFP_KERNEL);
if (!ppace)
return;
for (i = 0; i < num_aces; ++i) {
ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
ppace[i] = (struct smb_ace *) (acl_base + acl_size);
#ifdef CONFIG_CIFS_DEBUG2
dump_ace(ppace[i], end_of_acl);
#endif
@ -849,7 +849,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
/* memcpy((void *)(&(cifscred->aces[i])),
(void *)ppace[i],
sizeof(struct cifs_ace)); */
sizeof(struct smb_ace)); */
acl_base = (char *)ppace[i];
acl_size = le16_to_cpu(ppace[i]->size);
@ -861,7 +861,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
return;
}
unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
unsigned int setup_authusers_ACE(struct smb_ace *pntace)
{
int i;
unsigned int ace_size = 20;
@ -885,7 +885,7 @@ unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
* Fill in the special SID based on the mode. See
* https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
*/
unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
unsigned int setup_special_mode_ACE(struct smb_ace *pntace, __u64 nmode)
{
int i;
unsigned int ace_size = 28;
@ -907,7 +907,7 @@ 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)
unsigned int setup_special_user_owner_ACE(struct smb_ace *pntace)
{
int i;
unsigned int ace_size = 28;
@ -930,8 +930,8 @@ unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
}
static void populate_new_aces(char *nacl_base,
struct cifs_sid *pownersid,
struct cifs_sid *pgrpsid,
struct smb_sid *pownersid,
struct smb_sid *pgrpsid,
__u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
bool modefromsid)
{
@ -944,17 +944,17 @@ static void populate_new_aces(char *nacl_base,
__u64 deny_user_mode = 0;
__u64 deny_group_mode = 0;
bool sticky_set = false;
struct cifs_ace *pnntace = NULL;
struct smb_ace *pnntace = NULL;
nmode = *pnmode;
num_aces = *pnum_aces;
nsize = *pnsize;
if (modefromsid) {
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += setup_special_mode_ACE(pnntace, nmode);
num_aces++;
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += setup_authusers_ACE(pnntace);
num_aces++;
goto set_size;
@ -967,7 +967,7 @@ static void populate_new_aces(char *nacl_base,
* updated in the inode.
*/
if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) {
if (!memcmp(pownersid, pgrpsid, sizeof(struct smb_sid))) {
/*
* Case when owner and group SIDs are the same.
* Set the more restrictive of the two modes.
@ -992,7 +992,7 @@ static void populate_new_aces(char *nacl_base,
sticky_set = true;
if (deny_user_mode) {
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
0700, ACCESS_DENIED, false);
num_aces++;
@ -1000,31 +1000,31 @@ static void populate_new_aces(char *nacl_base,
/* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
0070, ACCESS_DENIED, false);
num_aces++;
}
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
0700, ACCESS_ALLOWED, true);
num_aces++;
/* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
0070, ACCESS_DENIED, false);
num_aces++;
}
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
0070, ACCESS_ALLOWED, !sticky_set);
num_aces++;
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
0007, ACCESS_ALLOWED, !sticky_set);
num_aces++;
@ -1034,31 +1034,31 @@ set_size:
*pnsize = nsize;
}
static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *pndacl,
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
struct smb_sid *pnownersid, struct smb_sid *pngrpsid)
{
int i;
u16 size = 0;
struct cifs_ace *pntace = NULL;
struct smb_ace *pntace = NULL;
char *acl_base = NULL;
u32 src_num_aces = 0;
u16 nsize = 0;
struct cifs_ace *pnntace = NULL;
struct smb_ace *pnntace = NULL;
char *nacl_base = NULL;
u16 ace_size = 0;
acl_base = (char *)pdacl;
size = sizeof(struct cifs_acl);
size = sizeof(struct smb_acl);
src_num_aces = le32_to_cpu(pdacl->num_aces);
nacl_base = (char *)pndacl;
nsize = sizeof(struct cifs_acl);
nsize = sizeof(struct smb_acl);
/* Go through all the ACEs */
for (i = 0; i < src_num_aces; ++i) {
pntace = (struct cifs_ace *) (acl_base + size);
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pntace = (struct smb_ace *) (acl_base + size);
pnntace = (struct smb_ace *) (nacl_base + nsize);
if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
@ -1074,24 +1074,24 @@ static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl
return nsize;
}
static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
__u64 *pnmode, bool mode_from_sid)
{
int i;
u16 size = 0;
struct cifs_ace *pntace = NULL;
struct smb_ace *pntace = NULL;
char *acl_base = NULL;
u32 src_num_aces = 0;
u16 nsize = 0;
struct cifs_ace *pnntace = NULL;
struct smb_ace *pnntace = NULL;
char *nacl_base = NULL;
u32 num_aces = 0;
bool new_aces_set = false;
/* Assuming that pndacl and pnmode are never NULL */
nacl_base = (char *)pndacl;
nsize = sizeof(struct cifs_acl);
nsize = sizeof(struct smb_acl);
/* If pdacl is NULL, we don't have a src. Simply populate new ACL. */
if (!pdacl) {
@ -1103,12 +1103,12 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
}
acl_base = (char *)pdacl;
size = sizeof(struct cifs_acl);
size = sizeof(struct smb_acl);
src_num_aces = le32_to_cpu(pdacl->num_aces);
/* Retain old ACEs which we can retain */
for (i = 0; i < src_num_aces; ++i) {
pntace = (struct cifs_ace *) (acl_base + size);
pntace = (struct smb_ace *) (acl_base + size);
if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
/* Place the new ACEs in between existing explicit and inherited */
@ -1130,7 +1130,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
}
/* update the pointer to the next ACE to populate*/
pnntace = (struct cifs_ace *) (nacl_base + nsize);
pnntace = (struct smb_ace *) (nacl_base + nsize);
nsize += cifs_copy_ace(pnntace, pntace, NULL);
num_aces++;
@ -1156,7 +1156,7 @@ finalize_dacl:
return 0;
}
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
static int parse_sid(struct smb_sid *psid, char *end_of_acl)
{
/* BB need to add parm so we can store the SID BB */
@ -1191,24 +1191,24 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
/* Convert CIFS ACL to POSIX form */
static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
struct smb_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
bool get_mode_from_special_sid)
{
int rc = 0;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
struct smb_acl *dacl_ptr; /* no need for SACL ptr */
char *end_of_acl = ((char *)pntsd) + acl_len;
__u32 dacloffset;
if (pntsd == NULL)
return -EIO;
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
group_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
dacloffset = le32_to_cpu(pntsd->dacloffset);
dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
le32_to_cpu(pntsd->gsidoffset),
@ -1249,7 +1249,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,
static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd,
__u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
bool mode_from_sid, bool id_from_sid, int *aclflag)
{
@ -1257,30 +1257,30 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
__u32 dacloffset;
__u32 ndacloffset;
__u32 sidsoffset;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
struct smb_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */
struct smb_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
char *end_of_acl = ((char *)pntsd) + secdesclen;
u16 size = 0;
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
cifs_dbg(VFS, "Server returned illegal ACL size\n");
return -EINVAL;
}
}
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
group_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
ndacloffset = sizeof(struct cifs_ntsd);
ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
ndacloffset = sizeof(struct smb_ntsd);
ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset);
ndacl_ptr->revision =
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
@ -1297,15 +1297,15 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
*aclflag |= CIFS_ACL_DACL;
} else {
ndacloffset = sizeof(struct cifs_ntsd);
ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
ndacloffset = sizeof(struct smb_ntsd);
ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset);
ndacl_ptr->revision =
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
if (uid_valid(uid)) { /* chown */
uid_t id;
nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid),
nowner_sid_ptr = kzalloc(sizeof(struct smb_sid),
GFP_KERNEL);
if (!nowner_sid_ptr) {
rc = -ENOMEM;
@ -1334,7 +1334,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
}
if (gid_valid(gid)) { /* chgrp */
gid_t id;
ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid),
ngroup_sid_ptr = kzalloc(sizeof(struct smb_sid),
GFP_KERNEL);
if (!ngroup_sid_ptr) {
rc = -ENOMEM;
@ -1385,11 +1385,11 @@ chown_chgrp_exit:
}
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
const struct cifs_fid *cifsfid, u32 *pacllen,
u32 __maybe_unused unused)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
unsigned int xid;
int rc;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
@ -1410,10 +1410,10 @@ struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
return pntsd;
}
static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
static struct smb_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
const char *path, u32 *pacllen)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
int oplock = 0;
unsigned int xid;
int rc;
@ -1454,11 +1454,11 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
}
/* Retrieve an ACL from the server */
struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct inode *inode, const char *path,
u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
struct cifsFileInfo *open_file = NULL;
if (inode)
@ -1472,7 +1472,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
}
/* Set an ACL on the server */
int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen,
struct inode *inode, const char *path, int aclflag)
{
int oplock = 0;
@ -1528,7 +1528,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
struct inode *inode, bool mode_from_special_sid,
const char *path, const struct cifs_fid *pfid)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
u32 acllen = 0;
int rc = 0;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
@ -1580,9 +1580,9 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
__u32 secdesclen = 0;
__u32 nsecdesclen = 0;
__u32 dacloffset = 0;
struct cifs_acl *dacl_ptr = NULL;
struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
struct smb_acl *dacl_ptr = NULL;
struct smb_ntsd *pntsd = NULL; /* acl obtained from server */
struct smb_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
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;
@ -1625,18 +1625,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
nsecdesclen = secdesclen;
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
if (mode_from_sid)
nsecdesclen += 2 * sizeof(struct cifs_ace);
nsecdesclen += 2 * sizeof(struct smb_ace);
else /* cifsacl */
nsecdesclen += 5 * sizeof(struct cifs_ace);
nsecdesclen += 5 * sizeof(struct smb_ace);
} else { /* chown */
/* When ownership changes, changes new owner sid length could be different */
nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2);
dacloffset = le32_to_cpu(pntsd->dacloffset);
if (dacloffset) {
dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
if (mode_from_sid)
nsecdesclen +=
le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
else /* cifsacl */
nsecdesclen += le16_to_cpu(dacl_ptr->size);
}

View File

@ -9,8 +9,7 @@
#ifndef _CIFSACL_H
#define _CIFSACL_H
#define NUM_AUTHS (6) /* number of authority fields */
#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
#include "../common/smbacl.h"
#define READ_BIT 0x4
#define WRITE_BIT 0x2
@ -23,101 +22,13 @@
#define UBITSHIFT 6
#define GBITSHIFT 3
#define ACCESS_ALLOWED 0
#define ACCESS_DENIED 1
#define SIDOWNER 1
#define SIDGROUP 2
/*
* Security Descriptor length containing DACL with 3 ACEs (one each for
* owner, group and world).
*/
#define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \
sizeof(struct cifs_acl) + \
(sizeof(struct cifs_ace) * 4))
/*
* Maximum size of a string representation of a SID:
*
* The fields are unsigned values in decimal. So:
*
* u8: max 3 bytes in decimal
* u32: max 10 bytes in decimal
*
* "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
*
* For authority field, max is when all 6 values are non-zero and it must be
* represented in hex. So "-0x" + 12 hex digits.
*
* Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
*/
#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
struct cifs_ntsd {
__le16 revision; /* revision level */
__le16 type;
__le32 osidoffset;
__le32 gsidoffset;
__le32 sacloffset;
__le32 dacloffset;
} __attribute__((packed));
struct cifs_sid {
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __attribute__((packed));
/* size of a struct cifs_sid, sans sub_auth array */
#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
struct cifs_acl {
__le16 revision; /* revision level */
__le16 size;
__le32 num_aces;
} __attribute__((packed));
/* ACE types - see MS-DTYP 2.4.4.1 */
#define ACCESS_ALLOWED_ACE_TYPE 0x00
#define ACCESS_DENIED_ACE_TYPE 0x01
#define SYSTEM_AUDIT_ACE_TYPE 0x02
#define SYSTEM_ALARM_ACE_TYPE 0x03
#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
/* ACE flags */
#define OBJECT_INHERIT_ACE 0x01
#define CONTAINER_INHERIT_ACE 0x02
#define NO_PROPAGATE_INHERIT_ACE 0x04
#define INHERIT_ONLY_ACE 0x08
#define INHERITED_ACE 0x10
#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
#define FAILED_ACCESS_ACE_FLAG 0x80
struct cifs_ace {
__u8 type; /* see above and MS-DTYP 2.4.4.1 */
__u8 flags;
__le16 size;
__le32 access_req;
struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
} __attribute__((packed));
#define DEFAULT_SEC_DESC_LEN (sizeof(struct smb_ntsd) + \
sizeof(struct smb_acl) + \
(sizeof(struct smb_ace) * 4))
/*
* The current SMB3 form of security descriptor is similar to what was used for
@ -194,6 +105,6 @@ struct owner_group_sids {
* Minimum security descriptor can be one without any SACL and DACL and can
* consist of revision, type, and two sids of minimum size for owner and group
*/
#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
#define MIN_SEC_DESC_LEN (sizeof(struct smb_ntsd) + (2 * MIN_SID_LEN))
#endif /* _CIFSACL_H */

View File

@ -106,7 +106,6 @@ extern int cifs_flush(struct file *, fl_owner_t id);
extern int cifs_file_mmap(struct file *file, struct vm_area_struct *vma);
extern int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma);
extern const struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file);
extern int cifs_readdir(struct file *file, struct dir_context *ctx);
/* Functions related to dir entries */

View File

@ -202,10 +202,10 @@ struct cifs_cred {
int gid;
int mode;
int cecount;
struct cifs_sid osid;
struct cifs_sid gsid;
struct smb_sid osid;
struct smb_sid gsid;
struct cifs_ntace *ntaces;
struct cifs_ace *aces;
struct smb_ace *aces;
};
struct cifs_open_info_data {
@ -231,8 +231,8 @@ struct cifs_open_info_data {
unsigned int eas_len;
} wsl;
char *symlink_target;
struct cifs_sid posix_owner;
struct cifs_sid posix_group;
struct smb_sid posix_owner;
struct smb_sid posix_group;
union {
struct smb2_file_all_info fi;
struct smb311_posix_qinfo posix_fi;
@ -536,12 +536,12 @@ struct smb_version_operations {
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
const char *, const void *, const __u16,
const struct nls_table *, struct cifs_sb_info *);
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
const char *, u32 *, u32);
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
const struct cifs_fid *, u32 *, u32);
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
int);
struct smb_ntsd * (*get_acl)(struct cifs_sb_info *cifssb, struct inode *ino,
const char *patch, u32 *plen, u32 info);
struct smb_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *cifssmb,
const struct cifs_fid *pfid, u32 *plen, u32 info);
int (*set_acl)(struct smb_ntsd *pntsd, __u32 len, struct inode *ino, const char *path,
int flag);
/* writepages retry size */
unsigned int (*wp_retry_size)(struct inode *);
/* get mtu credits */
@ -555,7 +555,7 @@ struct smb_version_operations {
bool (*dir_needs_close)(struct cifsFileInfo *);
long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
loff_t);
/* init transform request - used for encryption for now */
/* init transform (compress/encrypt) request */
int (*init_transform_rq)(struct TCP_Server_Info *, int num_rqst,
struct smb_rqst *, struct smb_rqst *);
int (*is_transform_hdr)(void *buf);
@ -1874,6 +1874,7 @@ static inline bool is_replayable_error(int error)
#define CIFS_HAS_CREDITS 0x0400 /* already has credits */
#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
#define CIFS_NO_SRV_RSP 0x1000 /* there is no server response */
#define CIFS_COMPRESS_REQ 0x4000 /* compress request before sending */
/* Security Flags: indicate type of session setup needed */
#define CIFSSEC_MAY_SIGN 0x00001

View File

@ -2573,12 +2573,6 @@ typedef struct {
} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
struct win_dev {
unsigned char type[8]; /* IntxCHR or IntxBLK or LnxFIFO or LnxSOCK */
__le64 major;
__le64 minor;
} __attribute__((packed));
struct fea {
unsigned char EA_flags;
__u8 name_len;

View File

@ -225,7 +225,7 @@ extern int cifs_set_file_info(struct inode *inode, struct iattr *attrs,
extern int cifs_rename_pending_delete(const char *full_path,
struct dentry *dentry,
const unsigned int xid);
extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
struct cifs_fattr *fattr, uint sidtype);
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr, struct inode *inode,
@ -233,19 +233,19 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
const char *path, const struct cifs_fid *pfid);
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
kuid_t uid, kgid_t gid);
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
const char *, u32 *, u32);
extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
const struct cifs_fid *, u32 *, u32);
extern struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifssmb, struct inode *ino,
const char *path, u32 *plen, u32 info);
extern struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifssb,
const struct cifs_fid *pfid, u32 *plen, u32 info);
extern struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap,
struct dentry *dentry, int type);
extern int cifs_set_acl(struct mnt_idmap *idmap,
struct dentry *dentry, struct posix_acl *acl, int type);
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 int set_cifs_acl(struct smb_ntsd *pntsd, __u32 len, struct inode *ino,
const char *path, int flag);
extern unsigned int setup_authusers_ACE(struct smb_ace *pace);
extern unsigned int setup_special_mode_ACE(struct smb_ace *pace, __u64 nmode);
extern unsigned int setup_special_user_owner_ACE(struct smb_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,
@ -570,9 +570,9 @@ extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
const struct nls_table *nls_codepage,
struct cifs_sb_info *cifs_sb);
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
__u16 fid, struct smb_ntsd **acl_inf, __u32 *buflen);
extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
struct cifs_ntsd *, __u32, int);
struct smb_ntsd *pntsd, __u32 len, int aclflag);
extern int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
const unsigned char *searchName,
struct posix_acl **acl, const int acl_type,
@ -676,6 +676,10 @@ char *extract_sharename(const char *unc);
int parse_reparse_point(struct reparse_data_buffer *buf,
u32 plen, struct cifs_sb_info *cifs_sb,
bool unicode, struct cifs_open_info_data *data);
int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev,
const char *symname);
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);

View File

@ -1076,8 +1076,8 @@ OldOpenRetry:
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
/* set file as system file if special file such
as fifo and server expecting SFU style and
/* set file as system file if special file such as fifo,
* socket, char or block and server expecting SFU style and
no Unix extensions */
if (create_options & CREATE_OPTION_SPECIAL)
@ -1193,8 +1193,8 @@ openRetry:
req->AllocationSize = 0;
/*
* Set file as system file if special file such as fifo and server
* expecting SFU style and no Unix extensions.
* Set file as system file if special file such as fifo, socket, char
* or block and server expecting SFU style and no Unix extensions.
*/
if (create_options & CREATE_OPTION_SPECIAL)
req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
@ -3427,7 +3427,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
/* Get Security Descriptor (by handle) from remote server for a file or dir */
int
CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
struct cifs_ntsd **acl_inf, __u32 *pbuflen)
struct smb_ntsd **acl_inf, __u32 *pbuflen)
{
int rc = 0;
int buf_type = 0;
@ -3497,7 +3497,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
/* check if buffer is big enough for the acl
header followed by the smallest SID */
if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||
(*pbuflen >= 64 * 1024)) {
cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
rc = -EINVAL;
@ -3517,7 +3517,7 @@ qsec_out:
int
CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
struct smb_ntsd *pntsd, __u32 acllen, int aclflag)
{
__u16 byte_count, param_count, data_count, param_offset, data_offset;
int rc = 0;

390
fs/smb/client/compress.c Normal file
View File

@ -0,0 +1,390 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2024, SUSE LLC
*
* Authors: Enzo Matsumiya <ematsumiya@suse.de>
*
* This file implements I/O compression support for SMB2 messages (SMB 3.1.1 only).
* See compress/ for implementation details of each algorithm.
*
* References:
* MS-SMB2 "3.1.4.4 Compressing the Message"
* MS-SMB2 "3.1.5.3 Decompressing the Chained Message"
* MS-XCA - for details of the supported algorithms
*/
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/uio.h>
#include <linux/sort.h>
#include "cifsglob.h"
#include "../common/smb2pdu.h"
#include "cifsproto.h"
#include "smb2proto.h"
#include "compress/lz77.h"
#include "compress.h"
/*
* The heuristic_*() functions below try to determine data compressibility.
*
* Derived from fs/btrfs/compression.c, changing coding style, some parameters, and removing
* unused parts.
*
* Read that file for better and more detailed explanation of the calculations.
*
* The algorithms are ran in a collected sample of the input (uncompressed) data.
* The sample is formed of 2K reads in PAGE_SIZE intervals, with a maximum size of 4M.
*
* Parsing the sample goes from "low-hanging fruits" (fastest algorithms, likely compressible)
* to "need more analysis" (likely uncompressible).
*/
struct bucket {
unsigned int count;
};
/**
* has_low_entropy() - Compute Shannon entropy of the sampled data.
* @bkt: Bytes counts of the sample.
* @slen: Size of the sample.
*
* Return: true if the level (percentage of number of bits that would be required to
* compress the data) is below the minimum threshold.
*
* Note:
* There _is_ an entropy level here that's > 65 (minimum threshold) that would indicate a
* possibility of compression, but compressing, or even further analysing, it would waste so much
* resources that it's simply not worth it.
*
* Also Shannon entropy is the last computed heuristic; if we got this far and ended up
* with uncertainty, just stay on the safe side and call it uncompressible.
*/
static bool has_low_entropy(struct bucket *bkt, size_t slen)
{
const size_t threshold = 65, max_entropy = 8 * ilog2(16);
size_t i, p, p2, len, sum = 0;
#define pow4(n) (n * n * n * n)
len = ilog2(pow4(slen));
for (i = 0; i < 256 && bkt[i].count > 0; i++) {
p = bkt[i].count;
p2 = ilog2(pow4(p));
sum += p * (len - p2);
}
sum /= slen;
return ((sum * 100 / max_entropy) <= threshold);
}
#define BYTE_DIST_BAD 0
#define BYTE_DIST_GOOD 1
#define BYTE_DIST_MAYBE 2
/**
* calc_byte_distribution() - Compute byte distribution on the sampled data.
* @bkt: Byte counts of the sample.
* @slen: Size of the sample.
*
* Return:
* BYTE_DIST_BAD: A "hard no" for compression -- a computed uniform distribution of
* the bytes (e.g. random or encrypted data).
* BYTE_DIST_GOOD: High probability (normal (Gaussian) distribution) of the data being
* compressible.
* BYTE_DIST_MAYBE: When computed byte distribution resulted in "low > n < high"
* grounds. has_low_entropy() should be used for a final decision.
*/
static int calc_byte_distribution(struct bucket *bkt, size_t slen)
{
const size_t low = 64, high = 200, threshold = slen * 90 / 100;
size_t sum = 0;
int i;
for (i = 0; i < low; i++)
sum += bkt[i].count;
if (sum > threshold)
return BYTE_DIST_BAD;
for (; i < high && bkt[i].count > 0; i++) {
sum += bkt[i].count;
if (sum > threshold)
break;
}
if (i <= low)
return BYTE_DIST_GOOD;
if (i >= high)
return BYTE_DIST_BAD;
return BYTE_DIST_MAYBE;
}
static bool is_mostly_ascii(const struct bucket *bkt)
{
size_t count = 0;
int i;
for (i = 0; i < 256; i++)
if (bkt[i].count > 0)
/* Too many non-ASCII (0-63) bytes. */
if (++count > 64)
return false;
return true;
}
static bool has_repeated_data(const u8 *sample, size_t len)
{
size_t s = len / 2;
return (!memcmp(&sample[0], &sample[s], s));
}
static int cmp_bkt(const void *_a, const void *_b)
{
const struct bucket *a = _a, *b = _b;
/* Reverse sort. */
if (a->count > b->count)
return -1;
return 1;
}
/*
* TODO:
* Support other iter types, if required.
* Only ITER_XARRAY is supported for now.
*/
static int collect_sample(const struct iov_iter *iter, ssize_t max, u8 *sample)
{
struct folio *folios[16], *folio;
unsigned int nr, i, j, npages;
loff_t start = iter->xarray_start + iter->iov_offset;
pgoff_t last, index = start / PAGE_SIZE;
size_t len, off, foff;
ssize_t ret = 0;
void *p;
int s = 0;
last = (start + max - 1) / PAGE_SIZE;
do {
nr = xa_extract(iter->xarray, (void **)folios, index, last, ARRAY_SIZE(folios),
XA_PRESENT);
if (nr == 0)
return -EIO;
for (i = 0; i < nr; i++) {
folio = folios[i];
npages = folio_nr_pages(folio);
foff = start - folio_pos(folio);
off = foff % PAGE_SIZE;
for (j = foff / PAGE_SIZE; j < npages; j++) {
size_t len2;
len = min_t(size_t, max, PAGE_SIZE - off);
len2 = min_t(size_t, len, SZ_2K);
p = kmap_local_page(folio_page(folio, j));
memcpy(&sample[s], p, len2);
kunmap_local(p);
if (ret < 0)
return ret;
s += len2;
if (len2 < SZ_2K || s >= max - SZ_2K)
return s;
max -= len;
if (max <= 0)
return s;
start += len;
off = 0;
index++;
}
}
} while (nr == ARRAY_SIZE(folios));
return s;
}
/**
* is_compressible() - Determines if a chunk of data is compressible.
* @data: Iterator containing uncompressed data.
*
* Return: true if @data is compressible, false otherwise.
*
* Tests shows that this function is quite reliable in predicting data compressibility,
* matching close to 1:1 with the behaviour of LZ77 compression success and failures.
*/
static bool is_compressible(const struct iov_iter *data)
{
const size_t read_size = SZ_2K, bkt_size = 256, max = SZ_4M;
struct bucket *bkt = NULL;
size_t len;
u8 *sample;
bool ret = false;
int i;
/* Preventive double check -- already checked in should_compress(). */
len = iov_iter_count(data);
if (unlikely(len < read_size))
return ret;
if (len - read_size > max)
len = max;
sample = kvzalloc(len, GFP_KERNEL);
if (!sample) {
WARN_ON_ONCE(1);
return ret;
}
/* Sample 2K bytes per page of the uncompressed data. */
i = collect_sample(data, len, sample);
if (i <= 0) {
WARN_ON_ONCE(1);
goto out;
}
len = i;
ret = true;
if (has_repeated_data(sample, len))
goto out;
bkt = kcalloc(bkt_size, sizeof(*bkt), GFP_KERNEL);
if (!bkt) {
WARN_ON_ONCE(1);
ret = false;
goto out;
}
for (i = 0; i < len; i++)
bkt[sample[i]].count++;
if (is_mostly_ascii(bkt))
goto out;
/* Sort in descending order */
sort(bkt, bkt_size, sizeof(*bkt), cmp_bkt, NULL);
i = calc_byte_distribution(bkt, len);
if (i != BYTE_DIST_MAYBE) {
ret = !!i;
goto out;
}
ret = has_low_entropy(bkt, len);
out:
kvfree(sample);
kfree(bkt);
return ret;
}
bool should_compress(const struct cifs_tcon *tcon, const struct smb_rqst *rq)
{
const struct smb2_hdr *shdr = rq->rq_iov->iov_base;
if (unlikely(!tcon || !tcon->ses || !tcon->ses->server))
return false;
if (!tcon->ses->server->compression.enabled)
return false;
if (!(tcon->share_flags & SMB2_SHAREFLAG_COMPRESS_DATA))
return false;
if (shdr->Command == SMB2_WRITE) {
const struct smb2_write_req *wreq = rq->rq_iov->iov_base;
if (le32_to_cpu(wreq->Length) < SMB_COMPRESS_MIN_LEN)
return false;
return is_compressible(&rq->rq_iter);
}
return (shdr->Command == SMB2_READ);
}
int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_send_fn send_fn)
{
struct iov_iter iter;
u32 slen, dlen;
void *src, *dst = NULL;
int ret;
if (!server || !rq || !rq->rq_iov || !rq->rq_iov->iov_base)
return -EINVAL;
if (rq->rq_iov->iov_len != sizeof(struct smb2_write_req))
return -EINVAL;
slen = iov_iter_count(&rq->rq_iter);
src = kvzalloc(slen, GFP_KERNEL);
if (!src) {
ret = -ENOMEM;
goto err_free;
}
/* Keep the original iter intact. */
iter = rq->rq_iter;
if (!copy_from_iter_full(src, slen, &iter)) {
ret = -EIO;
goto err_free;
}
/*
* This is just overprovisioning, as the algorithm will error out if @dst reaches 7/8
* of @slen.
*/
dlen = slen;
dst = kvzalloc(dlen, GFP_KERNEL);
if (!dst) {
ret = -ENOMEM;
goto err_free;
}
ret = lz77_compress(src, slen, dst, &dlen);
if (!ret) {
struct smb2_compression_hdr hdr = { 0 };
struct smb_rqst comp_rq = { .rq_nvec = 3, };
struct kvec iov[3];
hdr.ProtocolId = SMB2_COMPRESSION_TRANSFORM_ID;
hdr.OriginalCompressedSegmentSize = cpu_to_le32(slen);
hdr.CompressionAlgorithm = SMB3_COMPRESS_LZ77;
hdr.Flags = SMB2_COMPRESSION_FLAG_NONE;
hdr.Offset = cpu_to_le32(rq->rq_iov[0].iov_len);
iov[0].iov_base = &hdr;
iov[0].iov_len = sizeof(hdr);
iov[1] = rq->rq_iov[0];
iov[2].iov_base = dst;
iov[2].iov_len = dlen;
comp_rq.rq_iov = iov;
ret = send_fn(server, 1, &comp_rq);
} else if (ret == -EMSGSIZE || dlen >= slen) {
ret = send_fn(server, 1, rq);
}
err_free:
kvfree(dst);
kvfree(src);
return ret;
}

90
fs/smb/client/compress.h Normal file
View File

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2024, SUSE LLC
*
* Authors: Enzo Matsumiya <ematsumiya@suse.de>
*
* This file implements I/O compression support for SMB2 messages (SMB 3.1.1 only).
* See compress/ for implementation details of each algorithm.
*
* References:
* MS-SMB2 "3.1.4.4 Compressing the Message" - for compression details
* MS-SMB2 "3.1.5.3 Decompressing the Chained Message" - for decompression details
* MS-XCA - for details of the supported algorithms
*/
#ifndef _SMB_COMPRESS_H
#define _SMB_COMPRESS_H
#include <linux/uio.h>
#include <linux/kernel.h>
#include "../common/smb2pdu.h"
#include "cifsglob.h"
/* sizeof(smb2_compression_hdr) - sizeof(OriginalPayloadSize) */
#define SMB_COMPRESS_HDR_LEN 16
/* sizeof(smb2_compression_payload_hdr) - sizeof(OriginalPayloadSize) */
#define SMB_COMPRESS_PAYLOAD_HDR_LEN 8
#define SMB_COMPRESS_MIN_LEN PAGE_SIZE
#ifdef CONFIG_CIFS_COMPRESSION
typedef int (*compress_send_fn)(struct TCP_Server_Info *, int, struct smb_rqst *);
int smb_compress(struct TCP_Server_Info *server, struct smb_rqst *rq, compress_send_fn send_fn);
/**
* should_compress() - Determines if a request (write) or the response to a
* request (read) should be compressed.
* @tcon: tcon of the request is being sent to
* @rqst: request to evaluate
*
* Return: true iff:
* - compression was successfully negotiated with server
* - server has enabled compression for the share
* - it's a read or write request
* - (write only) request length is >= SMB_COMPRESS_MIN_LEN
* - (write only) is_compressible() returns 1
*
* Return false otherwise.
*/
bool should_compress(const struct cifs_tcon *tcon, const struct smb_rqst *rq);
/**
* smb_compress_alg_valid() - Validate a compression algorithm.
* @alg: Compression algorithm to check.
* @valid_none: Conditional check whether NONE algorithm should be
* considered valid or not.
*
* If @alg is SMB3_COMPRESS_NONE, this function returns @valid_none.
*
* Note that 'NONE' (0) compressor type is considered invalid in protocol
* negotiation, as it's never requested to/returned from the server.
*
* Return: true if @alg is valid/supported, false otherwise.
*/
static __always_inline int smb_compress_alg_valid(__le16 alg, bool valid_none)
{
if (alg == SMB3_COMPRESS_NONE)
return valid_none;
if (alg == SMB3_COMPRESS_LZ77 || alg == SMB3_COMPRESS_PATTERN)
return true;
return false;
}
#else /* !CONFIG_CIFS_COMPRESSION */
static inline int smb_compress(void *unused1, void *unused2, void *unused3)
{
return -EOPNOTSUPP;
}
static inline bool should_compress(void *unused1, void *unused2)
{
return false;
}
static inline int smb_compress_alg_valid(__le16 unused1, bool unused2)
{
return -EOPNOTSUPP;
}
#endif /* !CONFIG_CIFS_COMPRESSION */
#endif /* _SMB_COMPRESS_H */

View File

@ -0,0 +1,235 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2024, SUSE LLC
*
* Authors: Enzo Matsumiya <ematsumiya@suse.de>
*
* Implementation of the LZ77 "plain" compression algorithm, as per MS-XCA spec.
*/
#include <linux/slab.h>
#include <linux/sizes.h>
#include <linux/count_zeros.h>
#include <asm/unaligned.h>
#include "lz77.h"
/*
* Compression parameters.
*/
#define LZ77_MATCH_MIN_LEN 4
#define LZ77_MATCH_MIN_DIST 1
#define LZ77_MATCH_MAX_DIST SZ_1K
#define LZ77_HASH_LOG 15
#define LZ77_HASH_SIZE (1 << LZ77_HASH_LOG)
#define LZ77_STEP_SIZE sizeof(u64)
static __always_inline u8 lz77_read8(const u8 *ptr)
{
return get_unaligned(ptr);
}
static __always_inline u64 lz77_read64(const u64 *ptr)
{
return get_unaligned(ptr);
}
static __always_inline void lz77_write8(u8 *ptr, u8 v)
{
put_unaligned(v, ptr);
}
static __always_inline void lz77_write16(u16 *ptr, u16 v)
{
put_unaligned_le16(v, ptr);
}
static __always_inline void lz77_write32(u32 *ptr, u32 v)
{
put_unaligned_le32(v, ptr);
}
static __always_inline u32 lz77_match_len(const void *wnd, const void *cur, const void *end)
{
const void *start = cur;
u64 diff;
/* Safe for a do/while because otherwise we wouldn't reach here from the main loop. */
do {
diff = lz77_read64(cur) ^ lz77_read64(wnd);
if (!diff) {
cur += LZ77_STEP_SIZE;
wnd += LZ77_STEP_SIZE;
continue;
}
/* This computes the number of common bytes in @diff. */
cur += count_trailing_zeros(diff) >> 3;
return (cur - start);
} while (likely(cur + LZ77_STEP_SIZE < end));
while (cur < end && lz77_read8(cur++) == lz77_read8(wnd++))
;
return (cur - start);
}
static __always_inline void *lz77_write_match(void *dst, void **nib, u32 dist, u32 len)
{
len -= 3;
dist--;
dist <<= 3;
if (len < 7) {
lz77_write16(dst, dist + len);
return dst + 2;
}
dist |= 7;
lz77_write16(dst, dist);
dst += 2;
len -= 7;
if (!*nib) {
lz77_write8(dst, umin(len, 15));
*nib = dst;
dst++;
} else {
u8 *b = *nib;
lz77_write8(b, *b | umin(len, 15) << 4);
*nib = NULL;
}
if (len < 15)
return dst;
len -= 15;
if (len < 255) {
lz77_write8(dst, len);
return dst + 1;
}
lz77_write8(dst, 0xff);
dst++;
len += 7 + 15;
if (len <= 0xffff) {
lz77_write16(dst, len);
return dst + 2;
}
lz77_write16(dst, 0);
dst += 2;
lz77_write32(dst, len);
return dst + 4;
}
noinline int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen)
{
const void *srcp, *end;
void *dstp, *nib, *flag_pos;
u32 flag_count = 0;
long flag = 0;
u64 *htable;
srcp = src;
end = src + slen;
dstp = dst;
nib = NULL;
flag_pos = dstp;
dstp += 4;
htable = kvcalloc(LZ77_HASH_SIZE, sizeof(*htable), GFP_KERNEL);
if (!htable)
return -ENOMEM;
/* Main loop. */
do {
u32 dist, len = 0;
const void *wnd;
u64 hash;
hash = ((lz77_read64(srcp) << 24) * 889523592379ULL) >> (64 - LZ77_HASH_LOG);
wnd = src + htable[hash];
htable[hash] = srcp - src;
dist = srcp - wnd;
if (dist && dist < LZ77_MATCH_MAX_DIST)
len = lz77_match_len(wnd, srcp, end);
if (len < LZ77_MATCH_MIN_LEN) {
lz77_write8(dstp, lz77_read8(srcp));
dstp++;
srcp++;
flag <<= 1;
flag_count++;
if (flag_count == 32) {
lz77_write32(flag_pos, flag);
flag_count = 0;
flag_pos = dstp;
dstp += 4;
}
continue;
}
/*
* Bail out if @dstp reached >= 7/8 of @slen -- already compressed badly, not worth
* going further.
*/
if (unlikely(dstp - dst >= slen - (slen >> 3))) {
*dlen = slen;
goto out;
}
dstp = lz77_write_match(dstp, &nib, dist, len);
srcp += len;
flag = (flag << 1) | 1;
flag_count++;
if (flag_count == 32) {
lz77_write32(flag_pos, flag);
flag_count = 0;
flag_pos = dstp;
dstp += 4;
}
} while (likely(srcp + LZ77_STEP_SIZE < end));
while (srcp < end) {
u32 c = umin(end - srcp, 32 - flag_count);
memcpy(dstp, srcp, c);
dstp += c;
srcp += c;
flag <<= c;
flag_count += c;
if (flag_count == 32) {
lz77_write32(flag_pos, flag);
flag_count = 0;
flag_pos = dstp;
dstp += 4;
}
}
flag <<= (32 - flag_count);
flag |= (1 << (32 - flag_count)) - 1;
lz77_write32(flag_pos, flag);
*dlen = dstp - dst;
out:
kvfree(htable);
if (*dlen < slen)
return 0;
return -EMSGSIZE;
}

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2024, SUSE LLC
*
* Authors: Enzo Matsumiya <ematsumiya@suse.de>
*
* Implementation of the LZ77 "plain" compression algorithm, as per MS-XCA spec.
*/
#ifndef _SMB_COMPRESS_LZ77_H
#define _SMB_COMPRESS_LZ77_H
#include <linux/kernel.h>
int lz77_compress(const void *src, u32 slen, void *dst, u32 *dlen);
#endif /* _SMB_COMPRESS_LZ77_H */

View File

@ -1009,11 +1009,10 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
}
if (!list_empty(&server->pending_mid_q)) {
struct list_head dispose_list;
struct mid_q_entry *mid_entry;
struct list_head *tmp, *tmp2;
LIST_HEAD(dispose_list);
INIT_LIST_HEAD(&dispose_list);
spin_lock(&server->mid_lock);
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
@ -4081,7 +4080,7 @@ __cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
ses = cifs_get_smb_ses(master_tcon->ses->server, ctx);
if (IS_ERR(ses)) {
tcon = (struct cifs_tcon *)ses;
tcon = ERR_CAST(ses);
cifs_put_tcp_session(master_tcon->ses->server, 0);
goto out;
}

View File

@ -1403,7 +1403,7 @@ void
cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
{
struct cifsFileInfo *open_file, *tmp;
struct list_head tmp_list;
LIST_HEAD(tmp_list);
if (!tcon->use_persistent || !tcon->need_reopen_files)
return;
@ -1411,7 +1411,6 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
tcon->need_reopen_files = false;
cifs_dbg(FYI, "Reopen persistent handles\n");
INIT_LIST_HEAD(&tmp_list);
/* list all files open on tree connection, reopen resilient handles */
spin_lock(&tcon->open_file_lock);
@ -2094,9 +2093,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
struct cifsLockInfo *li, *tmp;
__u64 length = cifs_flock_len(flock);
struct list_head tmp_llist;
INIT_LIST_HEAD(&tmp_llist);
LIST_HEAD(tmp_llist);
/*
* Accessing maxBuf is racy with cifs_reconnect - need to store value

View File

@ -978,9 +978,12 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
switch (opt) {
case Opt_compress:
if (!IS_ENABLED(CONFIG_CIFS_COMPRESSION)) {
cifs_errorf(fc, "CONFIG_CIFS_COMPRESSION kernel config option is unset\n");
goto cifs_parse_mount_err;
}
ctx->compress = true;
cifs_dbg(VFS,
"SMB3 compression support is experimental\n");
cifs_dbg(VFS, "SMB3 compression support is experimental\n");
break;
case Opt_nodfs:
ctx->nodfs = 1;
@ -1896,14 +1899,17 @@ void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
if (ctx->mfsymlinks) {
if (ctx->sfu_emul) {
/*
* Our SFU ("Services for Unix" emulation does not allow
* creating symlinks but does allow reading existing SFU
* symlinks (it does allow both creating and reading SFU
* style mknod and FIFOs though). When "mfsymlinks" and
* Our SFU ("Services for Unix") emulation allows now
* creating new and reading existing SFU symlinks.
* Older Linux kernel versions were not able to neither
* read existing nor create new SFU symlinks. But
* creating and reading SFU style mknod and FIFOs was
* supported for long time. When "mfsymlinks" and
* "sfu" are both enabled at the same time, it allows
* reading both types of symlinks, but will only create
* them with mfsymlinks format. This allows better
* Apple compatibility (probably better for Samba too)
* Apple compatibility, compatibility with older Linux
* kernel clients (probably better for Samba too)
* while still recognizing old Windows style symlinks.
*/
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");

View File

@ -529,6 +529,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
struct cifs_fid fid;
struct cifs_open_parms oparms;
struct cifs_io_parms io_parms = {0};
char *symlink_buf_utf16;
unsigned int symlink_len_utf16;
char buf[24];
unsigned int bytes_read;
char *pbuf;
@ -539,10 +541,11 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
fattr->cf_mode &= ~S_IFMT;
if (fattr->cf_eof == 0) {
cifs_dbg(FYI, "Fifo\n");
fattr->cf_mode |= S_IFIFO;
fattr->cf_dtype = DT_FIFO;
return 0;
} else if (fattr->cf_eof < 8) {
} else if (fattr->cf_eof > 1 && fattr->cf_eof < 8) {
fattr->cf_mode |= S_IFREG;
fattr->cf_dtype = DT_REG;
return -EINVAL; /* EOPNOTSUPP? */
@ -584,7 +587,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
&bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) {
if (memcmp("IntxBLK", pbuf, 8) == 0) {
if (memcmp("IntxBLK\0", pbuf, 8) == 0) {
cifs_dbg(FYI, "Block device\n");
fattr->cf_mode |= S_IFBLK;
fattr->cf_dtype = DT_BLK;
@ -596,7 +599,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
fattr->cf_rdev = MKDEV(mjr, mnr);
}
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
} else if (memcmp("IntxCHR\0", pbuf, 8) == 0) {
cifs_dbg(FYI, "Char device\n");
fattr->cf_mode |= S_IFCHR;
fattr->cf_dtype = DT_CHR;
@ -612,10 +615,37 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
cifs_dbg(FYI, "Socket\n");
fattr->cf_mode |= S_IFSOCK;
fattr->cf_dtype = DT_SOCK;
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
} else if (memcmp("IntxLNK\1", pbuf, 8) == 0) {
cifs_dbg(FYI, "Symlink\n");
fattr->cf_mode |= S_IFLNK;
fattr->cf_dtype = DT_LNK;
if ((fattr->cf_eof > 8) && (fattr->cf_eof % 2 == 0)) {
symlink_buf_utf16 = kmalloc(fattr->cf_eof-8 + 1, GFP_KERNEL);
if (symlink_buf_utf16) {
io_parms.offset = 8;
io_parms.length = fattr->cf_eof-8 + 1;
buf_type = CIFS_NO_BUFFER;
rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
&symlink_len_utf16,
&symlink_buf_utf16,
&buf_type);
if ((rc == 0) &&
(symlink_len_utf16 > 0) &&
(symlink_len_utf16 < fattr->cf_eof-8 + 1) &&
(symlink_len_utf16 % 2 == 0)) {
fattr->cf_symlink_target =
cifs_strndup_from_utf16(symlink_buf_utf16,
symlink_len_utf16,
true,
cifs_sb->local_nls);
if (!fattr->cf_symlink_target)
rc = -ENOMEM;
}
kfree(symlink_buf_utf16);
} else {
rc = -ENOMEM;
}
}
} else if (memcmp("LnxFIFO", pbuf, 8) == 0) {
cifs_dbg(FYI, "FIFO\n");
fattr->cf_mode |= S_IFIFO;
@ -625,6 +655,10 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
fattr->cf_dtype = DT_REG;
rc = -EOPNOTSUPP;
}
} else if ((rc == 0) && (bytes_read == 1) && (pbuf[0] == '\0')) {
cifs_dbg(FYI, "Socket\n");
fattr->cf_mode |= S_IFSOCK;
fattr->cf_dtype = DT_SOCK;
} else {
fattr->cf_mode |= S_IFREG; /* then it is a file */
fattr->cf_dtype = DT_REG;

View File

@ -606,6 +606,9 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
/* BB what if DFS and this volume is on different share? BB */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
rc = __cifs_sfu_make_node(xid, inode, direntry, pTcon,
full_path, S_IFLNK, 0, symname);
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
} else if (pTcon->unix_ext) {
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,

View File

@ -751,12 +751,11 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *cfile = NULL;
struct file_list *tmp_list, *tmp_next_list;
struct list_head file_head;
LIST_HEAD(file_head);
if (cifs_inode == NULL)
return;
INIT_LIST_HEAD(&file_head);
spin_lock(&cifs_inode->open_file_lock);
list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
if (delayed_work_pending(&cfile->deferred)) {
@ -787,9 +786,8 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
{
struct cifsFileInfo *cfile;
struct file_list *tmp_list, *tmp_next_list;
struct list_head file_head;
LIST_HEAD(file_head);
INIT_LIST_HEAD(&file_head);
spin_lock(&tcon->open_file_lock);
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
if (delayed_work_pending(&cfile->deferred)) {
@ -819,11 +817,10 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
{
struct cifsFileInfo *cfile;
struct file_list *tmp_list, *tmp_next_list;
struct list_head file_head;
void *page;
const char *full_path;
LIST_HEAD(file_head);
INIT_LIST_HEAD(&file_head);
page = alloc_dentry_path();
spin_lock(&tcon->open_file_lock);
list_for_each_entry(cfile, &tcon->openFileList, tlist) {

View File

@ -1078,7 +1078,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
/*
* Check if mounted with mount parm 'sfu' mount parm.
* SFU emulation should work with all servers, but only
* supports block and char device (no socket & fifo),
* supports block and char device, socket & fifo,
* and was used by default in earlier versions of Windows
*/
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))

View File

@ -21,7 +21,7 @@
#include "cifs_unicode.h"
#include "fscache.h"
#include "smb2proto.h"
#include "smb2status.h"
#include "../common/smb2status.h"
static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)
{
@ -196,9 +196,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
struct cifsLockInfo *li, *tmp;
__u64 length = 1 + flock->fl_end - flock->fl_start;
struct list_head tmp_llist;
INIT_LIST_HEAD(&tmp_llist);
LIST_HEAD(tmp_llist);
/*
* Accessing maxBuf is racy with cifs_reconnect - need to store value

View File

@ -24,7 +24,7 @@
#include "smb2pdu.h"
#include "smb2proto.h"
#include "cached_dir.h"
#include "smb2status.h"
#include "../common/smb2status.h"
static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
{
@ -315,7 +315,7 @@ replay_again:
SMB2_O_INFO_FILE, 0,
sizeof(struct smb311_posix_qinfo *) +
(PATH_MAX * 2) +
(sizeof(struct cifs_sid) * 2), 0, NULL);
(sizeof(struct smb_sid) * 2), 0, NULL);
} else {
rc = SMB2_query_info_init(tcon, server,
&rqst[num_rqst],
@ -325,7 +325,7 @@ replay_again:
SMB2_O_INFO_FILE, 0,
sizeof(struct smb311_posix_qinfo *) +
(PATH_MAX * 2) +
(sizeof(struct cifs_sid) * 2), 0, NULL);
(sizeof(struct smb_sid) * 2), 0, NULL);
}
if (!rc && (!cfile || num_rqst > 1)) {
smb2_set_next_command(tcon, &rqst[num_rqst]);

View File

@ -12,7 +12,7 @@
#include "cifs_debug.h"
#include "smb2pdu.h"
#include "smb2proto.h"
#include "smb2status.h"
#include "../common/smb2status.h"
#include "smb2glob.h"
#include "trace.h"

View File

@ -13,7 +13,7 @@
#include "smb2proto.h"
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "smb2status.h"
#include "../common/smb2status.h"
#include "smb2glob.h"
#include "nterr.h"
#include "cached_dir.h"

View File

@ -22,7 +22,7 @@
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "smb2status.h"
#include "../common/smb2status.h"
#include "smb2glob.h"
#include "cifs_ioctl.h"
#include "smbdirect.h"
@ -3050,11 +3050,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
return rc;
}
static struct cifs_ntsd *
static struct smb_ntsd *
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
unsigned int xid;
int rc = -EOPNOTSUPP;
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
@ -3079,11 +3079,11 @@ get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
}
static struct cifs_ntsd *
static struct smb_ntsd *
get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
const char *path, u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
unsigned int xid;
int rc;
@ -3146,7 +3146,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
}
static int
set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
set_smb2_acl(struct smb_ntsd *pnntsd, __u32 acllen,
struct inode *inode, const char *path, int aclflag)
{
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
@ -3204,12 +3204,12 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
}
/* Retrieve an ACL from the server */
static struct cifs_ntsd *
static struct smb_ntsd *
get_smb2_acl(struct cifs_sb_info *cifs_sb,
struct inode *inode, const char *path,
u32 *pacllen, u32 info)
{
struct cifs_ntsd *pntsd = NULL;
struct smb_ntsd *pntsd = NULL;
struct cifsFileInfo *open_file = NULL;
if (inode && !(info & SACL_SECINFO))
@ -5078,9 +5078,10 @@ static int smb2_next_header(struct TCP_Server_Info *server, char *buf,
return 0;
}
static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev)
const char *full_path, umode_t mode, dev_t dev,
const char *symname)
{
struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_open_parms oparms;
@ -5088,30 +5089,64 @@ static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_fid fid;
unsigned int bytes_written;
struct win_dev pdev = {};
struct kvec iov[2];
u8 type[8];
int type_len = 0;
struct {
__le64 major;
__le64 minor;
} __packed pdev = {};
__le16 *symname_utf16 = NULL;
u8 *data = NULL;
int data_len = 0;
struct kvec iov[3];
__u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
int rc;
switch (mode & S_IFMT) {
case S_IFCHR:
strscpy(pdev.type, "IntxCHR");
type_len = 8;
memcpy(type, "IntxCHR\0", type_len);
pdev.major = cpu_to_le64(MAJOR(dev));
pdev.minor = cpu_to_le64(MINOR(dev));
data = (u8 *)&pdev;
data_len = sizeof(pdev);
break;
case S_IFBLK:
strscpy(pdev.type, "IntxBLK");
type_len = 8;
memcpy(type, "IntxBLK\0", type_len);
pdev.major = cpu_to_le64(MAJOR(dev));
pdev.minor = cpu_to_le64(MINOR(dev));
data = (u8 *)&pdev;
data_len = sizeof(pdev);
break;
case S_IFLNK:
type_len = 8;
memcpy(type, "IntxLNK\1", type_len);
symname_utf16 = cifs_strndup_to_utf16(symname, strlen(symname),
&data_len, cifs_sb->local_nls,
NO_MAP_UNI_RSVD);
if (!symname_utf16) {
rc = -ENOMEM;
goto out;
}
data_len -= 2; /* symlink is without trailing wide-nul */
data = (u8 *)symname_utf16;
break;
case S_IFSOCK:
strscpy(pdev.type, "LnxSOCK");
type_len = 8;
strscpy(type, "LnxSOCK");
data = (u8 *)&pdev;
data_len = sizeof(pdev);
break;
case S_IFIFO:
strscpy(pdev.type, "LnxFIFO");
type_len = 8;
strscpy(type, "LnxFIFO");
data = (u8 *)&pdev;
data_len = sizeof(pdev);
break;
default:
return -EPERM;
rc = -EPERM;
goto out;
}
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE,
@ -5121,17 +5156,26 @@ static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
rc = server->ops->open(xid, &oparms, &oplock, NULL);
if (rc)
return rc;
goto out;
if (type_len + data_len > 0) {
io_parms.pid = current->tgid;
io_parms.tcon = tcon;
io_parms.length = sizeof(pdev);
iov[1].iov_base = &pdev;
iov[1].iov_len = sizeof(pdev);
io_parms.length = type_len + data_len;
iov[1].iov_base = type;
iov[1].iov_len = type_len;
iov[2].iov_base = data;
iov[2].iov_len = data_len;
rc = server->ops->sync_write(xid, &fid, &io_parms,
&bytes_written, iov, 1);
&bytes_written,
iov, ARRAY_SIZE(iov)-1);
}
server->ops->close(xid, tcon, &fid);
out:
kfree(symname_utf16);
return rc;
}
@ -5143,7 +5187,7 @@ int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
int rc;
rc = __cifs_sfu_make_node(xid, inode, dentry, tcon,
full_path, mode, dev);
full_path, mode, dev, NULL);
if (rc)
return rc;
@ -5172,7 +5216,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
/*
* Check if mounted with mount parm 'sfu' mount parm.
* SFU emulation should work with all servers, but only
* supports block and char device (no socket & fifo),
* supports block and char device, socket & fifo,
* and was used by default in earlier versions of Windows
*/
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {

View File

@ -32,7 +32,7 @@
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "ntlmssp.h"
#include "smb2status.h"
#include "../common/smb2status.h"
#include "smb2glob.h"
#include "cifspdu.h"
#include "cifs_spnego.h"
@ -42,6 +42,7 @@
#include "dfs_cache.h"
#endif
#include "cached_dir.h"
#include "compress.h"
/*
* The following table defines the expected "StructureSize" of SMB2 requests
@ -2623,7 +2624,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
unsigned int group_offset = 0;
struct smb3_acl acl = {};
*len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8);
*len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * 4), 8);
if (set_owner) {
/* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
@ -2672,21 +2673,21 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
ptr += sizeof(struct smb3_acl);
/* create one ACE to hold the mode embedded in reserved special SID */
acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode);
acelen = setup_special_mode_ACE((struct smb_ace *)ptr, (__u64)mode);
ptr += acelen;
acl_size = acelen + sizeof(struct smb3_acl);
ace_count = 1;
if (set_owner) {
/* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr);
acelen = setup_special_user_owner_ACE((struct smb_ace *)ptr);
ptr += acelen;
acl_size += acelen;
ace_count += 1;
}
/* and one more ACE to allow access for authenticated users */
acelen = setup_authusers_ACE((struct cifs_ace *)ptr);
acelen = setup_authusers_ACE((struct smb_ace *)ptr);
ptr += acelen;
acl_size += acelen;
ace_count += 1;
@ -3906,7 +3907,7 @@ 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);
(sizeof(struct smb_sid) * 2) + (PATH_MAX * 2);
*plen = 0;
return query_info(xid, tcon, persistent_fid, volatile_fid,
@ -5023,6 +5024,10 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
flags |= CIFS_HAS_CREDITS;
}
/* XXX: compression + encryption is unsupported for now */
if (((flags & CIFS_TRANSFORM_REQ) != CIFS_TRANSFORM_REQ) && should_compress(tcon, &rqst))
flags |= CIFS_COMPRESS_REQ;
rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
wdata, flags, &wdata->credits);
/* Can't touch wdata if rc == 0 */
@ -5686,7 +5691,7 @@ SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
int
SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
struct cifs_ntsd *pnntsd, int pacllen, int aclflag)
struct smb_ntsd *pnntsd, int pacllen, int aclflag)
{
return send_set_info(xid, tcon, persistent_fid, volatile_fid,
current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,

View File

@ -364,8 +364,8 @@ struct create_posix_rsp {
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 */
struct smb_sid owner; /* var-sized on the wire */
struct smb_sid group; /* var-sized on the wire */
} __packed;
#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2
@ -408,8 +408,8 @@ struct smb2_posix_info {
struct smb2_posix_info_parsed {
const struct smb2_posix_info *base;
size_t size;
struct cifs_sid owner;
struct cifs_sid group;
struct smb_sid owner;
struct smb_sid group;
int name_len;
const u8 *name;
};

View File

@ -238,7 +238,7 @@ extern int SMB2_set_info_init(struct cifs_tcon *tcon,
extern void SMB2_set_info_free(struct smb_rqst *rqst);
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
struct smb_ntsd *pnntsd, int pacllen, int aclflag);
extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
struct smb2_file_full_ea_info *buf, int len);

View File

@ -23,7 +23,7 @@
#include "cifsproto.h"
#include "smb2proto.h"
#include "cifs_debug.h"
#include "smb2status.h"
#include "../common/smb2status.h"
#include "smb2glob.h"
static int

View File

@ -1586,10 +1586,8 @@ static struct smbd_connection *_smbd_get_connection(
conn_param.initiator_depth = 0;
conn_param.responder_resources =
info->id->device->attrs.max_qp_rd_atom
< SMBD_CM_RESPONDER_RESOURCES ?
info->id->device->attrs.max_qp_rd_atom :
SMBD_CM_RESPONDER_RESOURCES;
min(info->id->device->attrs.max_qp_rd_atom,
SMBD_CM_RESPONDER_RESOURCES);
info->responder_resources = conn_param.responder_resources;
log_rdma_mr(INFO, "responder_resources=%d\n",
info->responder_resources);

View File

@ -28,6 +28,7 @@
#include "cifs_debug.h"
#include "smb2proto.h"
#include "smbdirect.h"
#include "compress.h"
/* Max number of iovectors we can use off the stack when sending requests. */
#define CIFS_MAX_IOV_SIZE 8
@ -432,6 +433,9 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
struct kvec *iov;
int rc;
if (flags & CIFS_COMPRESS_REQ)
return smb_compress(server, &rqst[0], __smb_send_rqst);
if (!(flags & CIFS_TRANSFORM_REQ))
return __smb_send_rqst(server, num_rqst, rqst);

View File

@ -162,7 +162,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
case XATTR_CIFS_ACL:
case XATTR_CIFS_NTSD:
case XATTR_CIFS_NTSD_FULL: {
struct cifs_ntsd *pacl;
struct smb_ntsd *pacl;
if (!value)
goto out;
@ -315,7 +315,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
* fetch owner and DACL otherwise
*/
u32 acllen, extra_info;
struct cifs_ntsd *pacl;
struct smb_ntsd *pacl;
if (pTcon->ses->server->ops->get_acl == NULL)
goto out; /* rc already EOPNOTSUPP */

View File

@ -901,6 +901,10 @@ struct ntstatus {
#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER cpu_to_le32(0xC0000369)
/*
* 'OCCURED' is typo in MS-ERREF, it should be 'OCCURRED',
* but we'll keep it consistent with MS-ERREF.
*/
#define STATUS_MCA_OCCURED cpu_to_le32(0xC000036A)
#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
#define STATUS_DRIVER_BLOCKED cpu_to_le32(0xC000036C)
@ -1769,3 +1773,5 @@ struct ntstatus {
#define STATUS_IPSEC_INVALID_PACKET cpu_to_le32(0xC0360005)
#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
#define STATUS_IPSEC_CLEAR_TEXT_DROP cpu_to_le32(0xC0360007)
#define STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP cpu_to_le32(0xC05D0000)
#define STATUS_INVALID_LOCK_RANGE cpu_to_le32(0xC00001a1)

121
fs/smb/common/smbacl.h Normal file
View File

@ -0,0 +1,121 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (c) International Business Machines Corp., 2007
* Author(s): Steve French (sfrench@us.ibm.com)
* Modified by Namjae Jeon (linkinjeon@kernel.org)
*/
#ifndef _COMMON_SMBACL_H
#define _COMMON_SMBACL_H
#define NUM_AUTHS (6) /* number of authority fields */
#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
/* ACE types - see MS-DTYP 2.4.4.1 */
#define ACCESS_ALLOWED_ACE_TYPE 0x00
#define ACCESS_DENIED_ACE_TYPE 0x01
#define SYSTEM_AUDIT_ACE_TYPE 0x02
#define SYSTEM_ALARM_ACE_TYPE 0x03
#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
/* ACE flags */
#define OBJECT_INHERIT_ACE 0x01
#define CONTAINER_INHERIT_ACE 0x02
#define NO_PROPAGATE_INHERIT_ACE 0x04
#define INHERIT_ONLY_ACE 0x08
#define INHERITED_ACE 0x10
#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
#define FAILED_ACCESS_ACE_FLAG 0x80
/*
* Maximum size of a string representation of a SID:
*
* The fields are unsigned values in decimal. So:
*
* u8: max 3 bytes in decimal
* u32: max 10 bytes in decimal
*
* "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
*
* For authority field, max is when all 6 values are non-zero and it must be
* represented in hex. So "-0x" + 12 hex digits.
*
* Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
*/
#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
#define DOMAIN_USER_RID_LE cpu_to_le32(513)
/*
* ACE types - see MS-DTYP 2.4.4.1
*/
enum {
ACCESS_ALLOWED,
ACCESS_DENIED,
};
/*
* Security ID types
*/
enum {
SIDOWNER = 1,
SIDGROUP,
SIDCREATOR_OWNER,
SIDCREATOR_GROUP,
SIDUNIX_USER,
SIDUNIX_GROUP,
SIDNFS_USER,
SIDNFS_GROUP,
SIDNFS_MODE,
};
struct smb_ntsd {
__le16 revision; /* revision level */
__le16 type;
__le32 osidoffset;
__le32 gsidoffset;
__le32 sacloffset;
__le32 dacloffset;
} __attribute__((packed));
struct smb_sid {
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __attribute__((packed));
/* size of a struct smb_sid, sans sub_auth array */
#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
struct smb_acl {
__le16 revision; /* revision level */
__le16 size;
__le32 num_aces;
} __attribute__((packed));
struct smb_ace {
__u8 type; /* see above and MS-DTYP 2.4.4.1 */
__u8 flags;
__le16 size;
__le32 access_req;
struct smb_sid sid; /* ie UUID of user or group who gets these perms */
} __attribute__((packed));
#endif /* _COMMON_SMBACL_H */

View File

@ -10,7 +10,7 @@
#include "oplock.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "../common/smb2status.h"
#include "connection.h"
#include "mgmt/user_session.h"
#include "mgmt/share_config.h"

View File

@ -15,7 +15,7 @@
#include "server.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "../common/smb2status.h"
#include "connection.h"
#include "transport_ipc.h"
#include "mgmt/user_session.h"

View File

@ -7,7 +7,7 @@
#include "glob.h"
#include "nterr.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "../common/smb2status.h"
#include "mgmt/user_session.h"
#include "connection.h"

View File

@ -30,7 +30,7 @@
#include "server.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "../common/smb2status.h"
#include "ksmbd_work.h"
#include "mgmt/user_config.h"
#include "mgmt/share_config.h"

View File

@ -9,7 +9,7 @@
#include "smb_common.h"
#include "server.h"
#include "misc.h"
#include "smbstatus.h"
#include "../common/smb2status.h"
#include "connection.h"
#include "ksmbd_work.h"
#include "mgmt/user_session.h"

View File

@ -8,6 +8,7 @@
#ifndef _SMBACL_H
#define _SMBACL_H
#include "../common/smbacl.h"
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/posix_acl.h>
@ -15,32 +16,6 @@
#include "mgmt/tree_connect.h"
#define NUM_AUTHS (6) /* number of authority fields */
#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
/*
* ACE types - see MS-DTYP 2.4.4.1
*/
enum {
ACCESS_ALLOWED,
ACCESS_DENIED,
};
/*
* Security ID types
*/
enum {
SIDOWNER = 1,
SIDGROUP,
SIDCREATOR_OWNER,
SIDCREATOR_GROUP,
SIDUNIX_USER,
SIDUNIX_GROUP,
SIDNFS_USER,
SIDNFS_GROUP,
SIDNFS_MODE,
};
/* Revision for ACLs */
#define SD_REVISION 1
@ -62,92 +37,8 @@ enum {
#define RM_CONTROL_VALID 0x4000
#define SELF_RELATIVE 0x8000
/* ACE types - see MS-DTYP 2.4.4.1 */
#define ACCESS_ALLOWED_ACE_TYPE 0x00
#define ACCESS_DENIED_ACE_TYPE 0x01
#define SYSTEM_AUDIT_ACE_TYPE 0x02
#define SYSTEM_ALARM_ACE_TYPE 0x03
#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13
/* ACE flags */
#define OBJECT_INHERIT_ACE 0x01
#define CONTAINER_INHERIT_ACE 0x02
#define NO_PROPAGATE_INHERIT_ACE 0x04
#define INHERIT_ONLY_ACE 0x08
#define INHERITED_ACE 0x10
#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
#define FAILED_ACCESS_ACE_FLAG 0x80
/*
* Maximum size of a string representation of a SID:
*
* The fields are unsigned values in decimal. So:
*
* u8: max 3 bytes in decimal
* u32: max 10 bytes in decimal
*
* "S-" + 3 bytes for version field + 15 for authority field + NULL terminator
*
* For authority field, max is when all 6 values are non-zero and it must be
* represented in hex. So "-0x" + 12 hex digits.
*
* Add 11 bytes for each subauthority field (10 bytes each + 1 for '-')
*/
#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
#define DOMAIN_USER_RID_LE cpu_to_le32(513)
struct ksmbd_conn;
struct smb_ntsd {
__le16 revision; /* revision level */
__le16 type;
__le32 osidoffset;
__le32 gsidoffset;
__le32 sacloffset;
__le32 dacloffset;
} __packed;
struct smb_sid {
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __packed;
/* size of a struct cifs_sid, sans sub_auth array */
#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
struct smb_acl {
__le16 revision; /* revision level */
__le16 size;
__le32 num_aces;
} __packed;
struct smb_ace {
__u8 type;
__u8 flags;
__le16 size;
__le32 access_req;
struct smb_sid sid; /* ie UUID of user or group who gets these perms */
} __packed;
struct smb_fattr {
kuid_t cf_uid;
kgid_t cf_gid;

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
#include "glob.h"
#include "connection.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "../common/smb2status.h"
#include "transport_rdma.h"
#define SMB_DIRECT_PORT_IWARP 5445