mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
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:
commit
4e0373f1f9
@ -204,4 +204,18 @@ config CIFS_ROOT
|
|||||||
|
|
||||||
Most people say N here.
|
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
|
endif
|
||||||
|
@ -33,3 +33,5 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
|
|||||||
cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
|
cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
|
||||||
|
|
||||||
cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o
|
cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o
|
||||||
|
|
||||||
|
cifs-$(CONFIG_CIFS_COMPRESSION) += compress.o compress/lz77.o
|
||||||
|
@ -349,6 +349,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
|||||||
seq_printf(m, ",ACL");
|
seq_printf(m, ",ACL");
|
||||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||||
seq_puts(m, ",WITNESS");
|
seq_puts(m, ",WITNESS");
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CIFS_COMPRESSION
|
||||||
|
seq_puts(m, ",COMPRESSION");
|
||||||
#endif
|
#endif
|
||||||
seq_putc(m, '\n');
|
seq_putc(m, '\n');
|
||||||
seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
|
seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
|
||||||
@ -475,7 +478,9 @@ skip_rdma:
|
|||||||
}
|
}
|
||||||
|
|
||||||
seq_puts(m, "\nCompression: ");
|
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");
|
seq_puts(m, "disabled on mount");
|
||||||
else if (server->compression.enabled)
|
else if (server->compression.enabled)
|
||||||
seq_printf(m, "enabled (%s)", compression_alg_str(server->compression.alg));
|
seq_printf(m, "enabled (%s)", compression_alg_str(server->compression.alg));
|
||||||
|
@ -27,18 +27,18 @@
|
|||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
|
|
||||||
/* security id for everyone/world system group */
|
/* 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} };
|
1, 1, {0, 0, 0, 0, 0, 1}, {0} };
|
||||||
/* security id for Authenticated Users system group */
|
/* 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)} };
|
1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
|
||||||
|
|
||||||
/* S-1-22-1 Unmapped Unix users */
|
/* 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} };
|
{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 */
|
/* 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} };
|
{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 MS NFS and Apple style UID/GID/mode */
|
||||||
|
|
||||||
/* S-1-5-88-1 Unix uid */
|
/* 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(88),
|
||||||
cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
||||||
|
|
||||||
/* S-1-5-88-2 Unix gid */
|
/* 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(88),
|
||||||
cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
||||||
|
|
||||||
/* S-1-5-88-3 Unix mode */
|
/* 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(88),
|
||||||
cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
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 *
|
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;
|
int i, len;
|
||||||
unsigned int saval;
|
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.
|
* the same returns zero, if they do not match returns non-zero.
|
||||||
*/
|
*/
|
||||||
static int
|
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 i;
|
||||||
int num_subauth, num_sat, num_saw;
|
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 */
|
/* compare all of the subauth values if any */
|
||||||
num_sat = ctsid->num_subauth;
|
num_sat = ctsid->num_subauth;
|
||||||
num_saw = cwsid->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) {
|
if (num_subauth) {
|
||||||
for (i = 0; i < num_subauth; ++i) {
|
for (i = 0; i < num_subauth; ++i) {
|
||||||
if (ctsid->sub_auth[i] != cwsid->sub_auth[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
|
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 i;
|
||||||
int num_subauth;
|
int num_subauth;
|
||||||
const struct cifs_sid *pwell_known_sid;
|
const struct smb_sid *pwell_known_sid;
|
||||||
|
|
||||||
if (!psid || (puid == NULL))
|
if (!psid || (puid == NULL))
|
||||||
return false;
|
return false;
|
||||||
@ -260,7 +260,7 @@ is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __u16
|
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;
|
int i;
|
||||||
__u16 size = 1 + 1 + 6;
|
__u16 size = 1 + 1 + 6;
|
||||||
@ -277,11 +277,11 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
int rc;
|
||||||
struct key *sidkey;
|
struct key *sidkey;
|
||||||
struct cifs_sid *ksid;
|
struct smb_sid *ksid;
|
||||||
unsigned int ksid_size;
|
unsigned int ksid_size;
|
||||||
char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
|
char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
|
||||||
const struct cred *saved_cred;
|
const struct cred *saved_cred;
|
||||||
@ -312,8 +312,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
|
|||||||
* it could be.
|
* it could be.
|
||||||
*/
|
*/
|
||||||
ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
|
ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
|
||||||
(struct cifs_sid *)&sidkey->payload :
|
(struct smb_sid *)&sidkey->payload :
|
||||||
(struct cifs_sid *)sidkey->payload.data[0];
|
(struct smb_sid *)sidkey->payload.data[0];
|
||||||
|
|
||||||
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
|
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
|
||||||
if (ksid_size > sidkey->datalen) {
|
if (ksid_size > sidkey->datalen) {
|
||||||
@ -336,7 +336,7 @@ invalidate_key:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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)
|
struct cifs_fattr *fattr, uint sidtype)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -515,43 +515,43 @@ exit_cifs_idmap(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* copy ntsd, owner sid, and group sid from a security descriptor to another */
|
/* copy ntsd, owner sid, and group sid from a security descriptor to another */
|
||||||
static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
|
static __u32 copy_sec_desc(const struct smb_ntsd *pntsd,
|
||||||
struct cifs_ntsd *pnntsd,
|
struct smb_ntsd *pnntsd,
|
||||||
__u32 sidsoffset,
|
__u32 sidsoffset,
|
||||||
struct cifs_sid *pownersid,
|
struct smb_sid *pownersid,
|
||||||
struct cifs_sid *pgrpsid)
|
struct smb_sid *pgrpsid)
|
||||||
{
|
{
|
||||||
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
||||||
struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
|
struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr;
|
||||||
|
|
||||||
/* copy security descriptor control portion */
|
/* copy security descriptor control portion */
|
||||||
pnntsd->revision = pntsd->revision;
|
pnntsd->revision = pntsd->revision;
|
||||||
pnntsd->type = pntsd->type;
|
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->sacloffset = 0;
|
||||||
pnntsd->osidoffset = cpu_to_le32(sidsoffset);
|
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 */
|
/* copy owner sid */
|
||||||
if (pownersid)
|
if (pownersid)
|
||||||
owner_sid_ptr = pownersid;
|
owner_sid_ptr = pownersid;
|
||||||
else
|
else
|
||||||
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
||||||
le32_to_cpu(pntsd->osidoffset));
|
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);
|
cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
|
||||||
|
|
||||||
/* copy group sid */
|
/* copy group sid */
|
||||||
if (pgrpsid)
|
if (pgrpsid)
|
||||||
group_sid_ptr = pgrpsid;
|
group_sid_ptr = pgrpsid;
|
||||||
else
|
else
|
||||||
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
group_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
||||||
le32_to_cpu(pntsd->gsidoffset));
|
le32_to_cpu(pntsd->gsidoffset));
|
||||||
ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
|
ngroup_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset +
|
||||||
sizeof(struct cifs_sid));
|
sizeof(struct smb_sid));
|
||||||
cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
|
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;
|
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;
|
__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;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
|
static __u16 fill_ace_for_sid(struct smb_ace *pntace,
|
||||||
const struct cifs_sid *psid, __u64 nmode,
|
const struct smb_sid *psid, __u64 nmode,
|
||||||
umode_t bits, __u8 access_type,
|
umode_t bits, __u8 access_type,
|
||||||
bool allow_delete_child)
|
bool allow_delete_child)
|
||||||
{
|
{
|
||||||
@ -723,7 +723,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
|
|||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#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;
|
int num_subauth;
|
||||||
|
|
||||||
@ -758,15 +758,15 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
||||||
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
|
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
|
||||||
struct cifs_fattr *fattr, bool mode_from_special_sid)
|
struct cifs_fattr *fattr, bool mode_from_special_sid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int num_aces = 0;
|
int num_aces = 0;
|
||||||
int acl_size;
|
int acl_size;
|
||||||
char *acl_base;
|
char *acl_base;
|
||||||
struct cifs_ace **ppace;
|
struct smb_ace **ppace;
|
||||||
|
|
||||||
/* BB need to add parm so we can store the SID BB */
|
/* 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);
|
fattr->cf_mode &= ~(0777);
|
||||||
|
|
||||||
acl_base = (char *)pdacl;
|
acl_base = (char *)pdacl;
|
||||||
acl_size = sizeof(struct cifs_acl);
|
acl_size = sizeof(struct smb_acl);
|
||||||
|
|
||||||
num_aces = le32_to_cpu(pdacl->num_aces);
|
num_aces = le32_to_cpu(pdacl->num_aces);
|
||||||
if (num_aces > 0) {
|
if (num_aces > 0) {
|
||||||
umode_t denied_mode = 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;
|
return;
|
||||||
ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
|
ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!ppace)
|
if (!ppace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < num_aces; ++i) {
|
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
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
dump_ace(ppace[i], end_of_acl);
|
dump_ace(ppace[i], end_of_acl);
|
||||||
#endif
|
#endif
|
||||||
@ -849,7 +849,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
|||||||
|
|
||||||
/* memcpy((void *)(&(cifscred->aces[i])),
|
/* memcpy((void *)(&(cifscred->aces[i])),
|
||||||
(void *)ppace[i],
|
(void *)ppace[i],
|
||||||
sizeof(struct cifs_ace)); */
|
sizeof(struct smb_ace)); */
|
||||||
|
|
||||||
acl_base = (char *)ppace[i];
|
acl_base = (char *)ppace[i];
|
||||||
acl_size = le16_to_cpu(ppace[i]->size);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
|
unsigned int setup_authusers_ACE(struct smb_ace *pntace)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int ace_size = 20;
|
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
|
* Fill in the special SID based on the mode. See
|
||||||
* https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
|
* 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;
|
int i;
|
||||||
unsigned int ace_size = 28;
|
unsigned int ace_size = 28;
|
||||||
@ -907,7 +907,7 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
|
|||||||
return ace_size;
|
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;
|
int i;
|
||||||
unsigned int ace_size = 28;
|
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,
|
static void populate_new_aces(char *nacl_base,
|
||||||
struct cifs_sid *pownersid,
|
struct smb_sid *pownersid,
|
||||||
struct cifs_sid *pgrpsid,
|
struct smb_sid *pgrpsid,
|
||||||
__u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
|
__u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
|
||||||
bool modefromsid)
|
bool modefromsid)
|
||||||
{
|
{
|
||||||
@ -944,17 +944,17 @@ static void populate_new_aces(char *nacl_base,
|
|||||||
__u64 deny_user_mode = 0;
|
__u64 deny_user_mode = 0;
|
||||||
__u64 deny_group_mode = 0;
|
__u64 deny_group_mode = 0;
|
||||||
bool sticky_set = false;
|
bool sticky_set = false;
|
||||||
struct cifs_ace *pnntace = NULL;
|
struct smb_ace *pnntace = NULL;
|
||||||
|
|
||||||
nmode = *pnmode;
|
nmode = *pnmode;
|
||||||
num_aces = *pnum_aces;
|
num_aces = *pnum_aces;
|
||||||
nsize = *pnsize;
|
nsize = *pnsize;
|
||||||
|
|
||||||
if (modefromsid) {
|
if (modefromsid) {
|
||||||
pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
pnntace = (struct smb_ace *) (nacl_base + nsize);
|
||||||
nsize += setup_special_mode_ACE(pnntace, nmode);
|
nsize += setup_special_mode_ACE(pnntace, nmode);
|
||||||
num_aces++;
|
num_aces++;
|
||||||
pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
pnntace = (struct smb_ace *) (nacl_base + nsize);
|
||||||
nsize += setup_authusers_ACE(pnntace);
|
nsize += setup_authusers_ACE(pnntace);
|
||||||
num_aces++;
|
num_aces++;
|
||||||
goto set_size;
|
goto set_size;
|
||||||
@ -967,7 +967,7 @@ static void populate_new_aces(char *nacl_base,
|
|||||||
* updated in the inode.
|
* 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.
|
* Case when owner and group SIDs are the same.
|
||||||
* Set the more restrictive of the two modes.
|
* Set the more restrictive of the two modes.
|
||||||
@ -992,7 +992,7 @@ static void populate_new_aces(char *nacl_base,
|
|||||||
sticky_set = true;
|
sticky_set = true;
|
||||||
|
|
||||||
if (deny_user_mode) {
|
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,
|
nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
|
||||||
0700, ACCESS_DENIED, false);
|
0700, ACCESS_DENIED, false);
|
||||||
num_aces++;
|
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*/
|
/* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
|
||||||
if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
|
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,
|
nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
|
||||||
0070, ACCESS_DENIED, false);
|
0070, ACCESS_DENIED, false);
|
||||||
num_aces++;
|
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,
|
nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
|
||||||
0700, ACCESS_ALLOWED, true);
|
0700, ACCESS_ALLOWED, true);
|
||||||
num_aces++;
|
num_aces++;
|
||||||
|
|
||||||
/* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
|
/* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
|
||||||
if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
|
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,
|
nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
|
||||||
0070, ACCESS_DENIED, false);
|
0070, ACCESS_DENIED, false);
|
||||||
num_aces++;
|
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,
|
nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
|
||||||
0070, ACCESS_ALLOWED, !sticky_set);
|
0070, ACCESS_ALLOWED, !sticky_set);
|
||||||
num_aces++;
|
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,
|
nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
|
||||||
0007, ACCESS_ALLOWED, !sticky_set);
|
0007, ACCESS_ALLOWED, !sticky_set);
|
||||||
num_aces++;
|
num_aces++;
|
||||||
@ -1034,31 +1034,31 @@ set_size:
|
|||||||
*pnsize = nsize;
|
*pnsize = nsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *pndacl,
|
||||||
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
|
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
|
||||||
struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
|
struct smb_sid *pnownersid, struct smb_sid *pngrpsid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u16 size = 0;
|
u16 size = 0;
|
||||||
struct cifs_ace *pntace = NULL;
|
struct smb_ace *pntace = NULL;
|
||||||
char *acl_base = NULL;
|
char *acl_base = NULL;
|
||||||
u32 src_num_aces = 0;
|
u32 src_num_aces = 0;
|
||||||
u16 nsize = 0;
|
u16 nsize = 0;
|
||||||
struct cifs_ace *pnntace = NULL;
|
struct smb_ace *pnntace = NULL;
|
||||||
char *nacl_base = NULL;
|
char *nacl_base = NULL;
|
||||||
u16 ace_size = 0;
|
u16 ace_size = 0;
|
||||||
|
|
||||||
acl_base = (char *)pdacl;
|
acl_base = (char *)pdacl;
|
||||||
size = sizeof(struct cifs_acl);
|
size = sizeof(struct smb_acl);
|
||||||
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
||||||
|
|
||||||
nacl_base = (char *)pndacl;
|
nacl_base = (char *)pndacl;
|
||||||
nsize = sizeof(struct cifs_acl);
|
nsize = sizeof(struct smb_acl);
|
||||||
|
|
||||||
/* Go through all the ACEs */
|
/* Go through all the ACEs */
|
||||||
for (i = 0; i < src_num_aces; ++i) {
|
for (i = 0; i < src_num_aces; ++i) {
|
||||||
pntace = (struct cifs_ace *) (acl_base + size);
|
pntace = (struct smb_ace *) (acl_base + size);
|
||||||
pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
pnntace = (struct smb_ace *) (nacl_base + nsize);
|
||||||
|
|
||||||
if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
|
if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
|
||||||
ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
|
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;
|
return nsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
|
||||||
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
|
struct smb_sid *pownersid, struct smb_sid *pgrpsid,
|
||||||
__u64 *pnmode, bool mode_from_sid)
|
__u64 *pnmode, bool mode_from_sid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u16 size = 0;
|
u16 size = 0;
|
||||||
struct cifs_ace *pntace = NULL;
|
struct smb_ace *pntace = NULL;
|
||||||
char *acl_base = NULL;
|
char *acl_base = NULL;
|
||||||
u32 src_num_aces = 0;
|
u32 src_num_aces = 0;
|
||||||
u16 nsize = 0;
|
u16 nsize = 0;
|
||||||
struct cifs_ace *pnntace = NULL;
|
struct smb_ace *pnntace = NULL;
|
||||||
char *nacl_base = NULL;
|
char *nacl_base = NULL;
|
||||||
u32 num_aces = 0;
|
u32 num_aces = 0;
|
||||||
bool new_aces_set = false;
|
bool new_aces_set = false;
|
||||||
|
|
||||||
/* Assuming that pndacl and pnmode are never NULL */
|
/* Assuming that pndacl and pnmode are never NULL */
|
||||||
nacl_base = (char *)pndacl;
|
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 is NULL, we don't have a src. Simply populate new ACL. */
|
||||||
if (!pdacl) {
|
if (!pdacl) {
|
||||||
@ -1103,12 +1103,12 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
acl_base = (char *)pdacl;
|
acl_base = (char *)pdacl;
|
||||||
size = sizeof(struct cifs_acl);
|
size = sizeof(struct smb_acl);
|
||||||
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
||||||
|
|
||||||
/* Retain old ACEs which we can retain */
|
/* Retain old ACEs which we can retain */
|
||||||
for (i = 0; i < src_num_aces; ++i) {
|
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)) {
|
if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
|
||||||
/* Place the new ACEs in between existing explicit and inherited */
|
/* 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*/
|
/* 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);
|
nsize += cifs_copy_ace(pnntace, pntace, NULL);
|
||||||
num_aces++;
|
num_aces++;
|
||||||
@ -1156,7 +1156,7 @@ finalize_dacl:
|
|||||||
return 0;
|
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 */
|
/* 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 */
|
/* Convert CIFS ACL to POSIX form */
|
||||||
static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
|
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)
|
bool get_mode_from_special_sid)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
||||||
struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
|
struct smb_acl *dacl_ptr; /* no need for SACL ptr */
|
||||||
char *end_of_acl = ((char *)pntsd) + acl_len;
|
char *end_of_acl = ((char *)pntsd) + acl_len;
|
||||||
__u32 dacloffset;
|
__u32 dacloffset;
|
||||||
|
|
||||||
if (pntsd == NULL)
|
if (pntsd == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
||||||
le32_to_cpu(pntsd->osidoffset));
|
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));
|
le32_to_cpu(pntsd->gsidoffset));
|
||||||
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
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",
|
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),
|
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
|
||||||
le32_to_cpu(pntsd->gsidoffset),
|
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 */
|
/* 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,
|
__u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
|
||||||
bool mode_from_sid, bool id_from_sid, int *aclflag)
|
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 dacloffset;
|
||||||
__u32 ndacloffset;
|
__u32 ndacloffset;
|
||||||
__u32 sidsoffset;
|
__u32 sidsoffset;
|
||||||
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
||||||
struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
|
struct smb_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
|
||||||
struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
|
struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */
|
||||||
struct cifs_acl *ndacl_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;
|
char *end_of_acl = ((char *)pntsd) + secdesclen;
|
||||||
u16 size = 0;
|
u16 size = 0;
|
||||||
|
|
||||||
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
||||||
if (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)) {
|
if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
|
||||||
cifs_dbg(VFS, "Server returned illegal ACL size\n");
|
cifs_dbg(VFS, "Server returned illegal ACL size\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
||||||
le32_to_cpu(pntsd->osidoffset));
|
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));
|
le32_to_cpu(pntsd->gsidoffset));
|
||||||
|
|
||||||
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
||||||
ndacloffset = sizeof(struct cifs_ntsd);
|
ndacloffset = sizeof(struct smb_ntsd);
|
||||||
ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
|
ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset);
|
||||||
ndacl_ptr->revision =
|
ndacl_ptr->revision =
|
||||||
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_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;
|
*aclflag |= CIFS_ACL_DACL;
|
||||||
} else {
|
} else {
|
||||||
ndacloffset = sizeof(struct cifs_ntsd);
|
ndacloffset = sizeof(struct smb_ntsd);
|
||||||
ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
|
ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset);
|
||||||
ndacl_ptr->revision =
|
ndacl_ptr->revision =
|
||||||
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
|
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
|
||||||
ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
|
ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
|
||||||
|
|
||||||
if (uid_valid(uid)) { /* chown */
|
if (uid_valid(uid)) { /* chown */
|
||||||
uid_t id;
|
uid_t id;
|
||||||
nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid),
|
nowner_sid_ptr = kzalloc(sizeof(struct smb_sid),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!nowner_sid_ptr) {
|
if (!nowner_sid_ptr) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
@ -1334,7 +1334,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|||||||
}
|
}
|
||||||
if (gid_valid(gid)) { /* chgrp */
|
if (gid_valid(gid)) { /* chgrp */
|
||||||
gid_t id;
|
gid_t id;
|
||||||
ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid),
|
ngroup_sid_ptr = kzalloc(sizeof(struct smb_sid),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!ngroup_sid_ptr) {
|
if (!ngroup_sid_ptr) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
@ -1385,11 +1385,11 @@ chown_chgrp_exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
#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,
|
const struct cifs_fid *cifsfid, u32 *pacllen,
|
||||||
u32 __maybe_unused unused)
|
u32 __maybe_unused unused)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int rc;
|
int rc;
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
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;
|
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)
|
const char *path, u32 *pacllen)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int rc;
|
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 */
|
/* 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,
|
struct inode *inode, const char *path,
|
||||||
u32 *pacllen, u32 info)
|
u32 *pacllen, u32 info)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
struct cifsFileInfo *open_file = NULL;
|
struct cifsFileInfo *open_file = NULL;
|
||||||
|
|
||||||
if (inode)
|
if (inode)
|
||||||
@ -1472,7 +1472,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set an ACL on the server */
|
/* 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)
|
struct inode *inode, const char *path, int aclflag)
|
||||||
{
|
{
|
||||||
int oplock = 0;
|
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,
|
struct inode *inode, bool mode_from_special_sid,
|
||||||
const char *path, const struct cifs_fid *pfid)
|
const char *path, const struct cifs_fid *pfid)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
u32 acllen = 0;
|
u32 acllen = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
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 secdesclen = 0;
|
||||||
__u32 nsecdesclen = 0;
|
__u32 nsecdesclen = 0;
|
||||||
__u32 dacloffset = 0;
|
__u32 dacloffset = 0;
|
||||||
struct cifs_acl *dacl_ptr = NULL;
|
struct smb_acl *dacl_ptr = NULL;
|
||||||
struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
|
struct smb_ntsd *pntsd = NULL; /* acl obtained from server */
|
||||||
struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to 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 cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
||||||
struct smb_version_operations *ops;
|
struct smb_version_operations *ops;
|
||||||
@ -1625,18 +1625,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
|||||||
nsecdesclen = secdesclen;
|
nsecdesclen = secdesclen;
|
||||||
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
||||||
if (mode_from_sid)
|
if (mode_from_sid)
|
||||||
nsecdesclen += 2 * sizeof(struct cifs_ace);
|
nsecdesclen += 2 * sizeof(struct smb_ace);
|
||||||
else /* cifsacl */
|
else /* cifsacl */
|
||||||
nsecdesclen += 5 * sizeof(struct cifs_ace);
|
nsecdesclen += 5 * sizeof(struct smb_ace);
|
||||||
} else { /* chown */
|
} else { /* chown */
|
||||||
/* When ownership changes, changes new owner sid length could be different */
|
/* 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);
|
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
||||||
if (dacloffset) {
|
if (dacloffset) {
|
||||||
dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
|
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
|
||||||
if (mode_from_sid)
|
if (mode_from_sid)
|
||||||
nsecdesclen +=
|
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 */
|
else /* cifsacl */
|
||||||
nsecdesclen += le16_to_cpu(dacl_ptr->size);
|
nsecdesclen += le16_to_cpu(dacl_ptr->size);
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
#ifndef _CIFSACL_H
|
#ifndef _CIFSACL_H
|
||||||
#define _CIFSACL_H
|
#define _CIFSACL_H
|
||||||
|
|
||||||
#define NUM_AUTHS (6) /* number of authority fields */
|
#include "../common/smbacl.h"
|
||||||
#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
|
|
||||||
|
|
||||||
#define READ_BIT 0x4
|
#define READ_BIT 0x4
|
||||||
#define WRITE_BIT 0x2
|
#define WRITE_BIT 0x2
|
||||||
@ -23,101 +22,13 @@
|
|||||||
#define UBITSHIFT 6
|
#define UBITSHIFT 6
|
||||||
#define GBITSHIFT 3
|
#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
|
* Security Descriptor length containing DACL with 3 ACEs (one each for
|
||||||
* owner, group and world).
|
* owner, group and world).
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \
|
#define DEFAULT_SEC_DESC_LEN (sizeof(struct smb_ntsd) + \
|
||||||
sizeof(struct cifs_acl) + \
|
sizeof(struct smb_acl) + \
|
||||||
(sizeof(struct cifs_ace) * 4))
|
(sizeof(struct smb_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));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The current SMB3 form of security descriptor is similar to what was used for
|
* 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
|
* 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
|
* 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 */
|
#endif /* _CIFSACL_H */
|
||||||
|
@ -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_mmap(struct file *file, struct vm_area_struct *vma);
|
||||||
extern int cifs_file_strict_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 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);
|
extern int cifs_readdir(struct file *file, struct dir_context *ctx);
|
||||||
|
|
||||||
/* Functions related to dir entries */
|
/* Functions related to dir entries */
|
||||||
|
@ -202,10 +202,10 @@ struct cifs_cred {
|
|||||||
int gid;
|
int gid;
|
||||||
int mode;
|
int mode;
|
||||||
int cecount;
|
int cecount;
|
||||||
struct cifs_sid osid;
|
struct smb_sid osid;
|
||||||
struct cifs_sid gsid;
|
struct smb_sid gsid;
|
||||||
struct cifs_ntace *ntaces;
|
struct cifs_ntace *ntaces;
|
||||||
struct cifs_ace *aces;
|
struct smb_ace *aces;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cifs_open_info_data {
|
struct cifs_open_info_data {
|
||||||
@ -231,8 +231,8 @@ struct cifs_open_info_data {
|
|||||||
unsigned int eas_len;
|
unsigned int eas_len;
|
||||||
} wsl;
|
} wsl;
|
||||||
char *symlink_target;
|
char *symlink_target;
|
||||||
struct cifs_sid posix_owner;
|
struct smb_sid posix_owner;
|
||||||
struct cifs_sid posix_group;
|
struct smb_sid posix_group;
|
||||||
union {
|
union {
|
||||||
struct smb2_file_all_info fi;
|
struct smb2_file_all_info fi;
|
||||||
struct smb311_posix_qinfo posix_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 *,
|
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
|
||||||
const char *, const void *, const __u16,
|
const char *, const void *, const __u16,
|
||||||
const struct nls_table *, struct cifs_sb_info *);
|
const struct nls_table *, struct cifs_sb_info *);
|
||||||
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
|
struct smb_ntsd * (*get_acl)(struct cifs_sb_info *cifssb, struct inode *ino,
|
||||||
const char *, u32 *, u32);
|
const char *patch, u32 *plen, u32 info);
|
||||||
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
|
struct smb_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *cifssmb,
|
||||||
const struct cifs_fid *, u32 *, u32);
|
const struct cifs_fid *pfid, u32 *plen, u32 info);
|
||||||
int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
|
int (*set_acl)(struct smb_ntsd *pntsd, __u32 len, struct inode *ino, const char *path,
|
||||||
int);
|
int flag);
|
||||||
/* writepages retry size */
|
/* writepages retry size */
|
||||||
unsigned int (*wp_retry_size)(struct inode *);
|
unsigned int (*wp_retry_size)(struct inode *);
|
||||||
/* get mtu credits */
|
/* get mtu credits */
|
||||||
@ -555,7 +555,7 @@ struct smb_version_operations {
|
|||||||
bool (*dir_needs_close)(struct cifsFileInfo *);
|
bool (*dir_needs_close)(struct cifsFileInfo *);
|
||||||
long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
|
long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t,
|
||||||
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,
|
int (*init_transform_rq)(struct TCP_Server_Info *, int num_rqst,
|
||||||
struct smb_rqst *, struct smb_rqst *);
|
struct smb_rqst *, struct smb_rqst *);
|
||||||
int (*is_transform_hdr)(void *buf);
|
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_HAS_CREDITS 0x0400 /* already has credits */
|
||||||
#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
|
#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
|
||||||
#define CIFS_NO_SRV_RSP 0x1000 /* there is no server response */
|
#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 */
|
/* Security Flags: indicate type of session setup needed */
|
||||||
#define CIFSSEC_MAY_SIGN 0x00001
|
#define CIFSSEC_MAY_SIGN 0x00001
|
||||||
|
@ -2573,12 +2573,6 @@ typedef struct {
|
|||||||
} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
|
} __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 {
|
struct fea {
|
||||||
unsigned char EA_flags;
|
unsigned char EA_flags;
|
||||||
__u8 name_len;
|
__u8 name_len;
|
||||||
|
@ -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,
|
extern int cifs_rename_pending_delete(const char *full_path,
|
||||||
struct dentry *dentry,
|
struct dentry *dentry,
|
||||||
const unsigned int xid);
|
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);
|
struct cifs_fattr *fattr, uint sidtype);
|
||||||
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||||
struct cifs_fattr *fattr, struct inode *inode,
|
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);
|
const char *path, const struct cifs_fid *pfid);
|
||||||
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
||||||
kuid_t uid, kgid_t gid);
|
kuid_t uid, kgid_t gid);
|
||||||
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
|
extern struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifssmb, struct inode *ino,
|
||||||
const char *, u32 *, u32);
|
const char *path, u32 *plen, u32 info);
|
||||||
extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
|
extern struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifssb,
|
||||||
const struct cifs_fid *, u32 *, u32);
|
const struct cifs_fid *pfid, u32 *plen, u32 info);
|
||||||
extern struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap,
|
extern struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap,
|
||||||
struct dentry *dentry, int type);
|
struct dentry *dentry, int type);
|
||||||
extern int cifs_set_acl(struct mnt_idmap *idmap,
|
extern int cifs_set_acl(struct mnt_idmap *idmap,
|
||||||
struct dentry *dentry, struct posix_acl *acl, int type);
|
struct dentry *dentry, struct posix_acl *acl, int type);
|
||||||
extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
|
extern int set_cifs_acl(struct smb_ntsd *pntsd, __u32 len, struct inode *ino,
|
||||||
const char *, int);
|
const char *path, int flag);
|
||||||
extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
|
extern unsigned int setup_authusers_ACE(struct smb_ace *pace);
|
||||||
extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
|
extern unsigned int setup_special_mode_ACE(struct smb_ace *pace, __u64 nmode);
|
||||||
extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
|
extern unsigned int setup_special_user_owner_ACE(struct smb_ace *pace);
|
||||||
|
|
||||||
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
|
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
|
||||||
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
|
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,
|
const struct nls_table *nls_codepage,
|
||||||
struct cifs_sb_info *cifs_sb);
|
struct cifs_sb_info *cifs_sb);
|
||||||
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
|
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,
|
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,
|
extern int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const unsigned char *searchName,
|
const unsigned char *searchName,
|
||||||
struct posix_acl **acl, const int acl_type,
|
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,
|
int parse_reparse_point(struct reparse_data_buffer *buf,
|
||||||
u32 plen, struct cifs_sb_info *cifs_sb,
|
u32 plen, struct cifs_sb_info *cifs_sb,
|
||||||
bool unicode, struct cifs_open_info_data *data);
|
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,
|
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
|
||||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
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);
|
||||||
|
@ -1076,8 +1076,8 @@ OldOpenRetry:
|
|||||||
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
|
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(access_flags_to_smbopen_mode(access_flags));
|
||||||
pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
|
pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
|
||||||
/* set file as system file if special file such
|
/* set file as system file if special file such as fifo,
|
||||||
as fifo and server expecting SFU style and
|
* socket, char or block and server expecting SFU style and
|
||||||
no Unix extensions */
|
no Unix extensions */
|
||||||
|
|
||||||
if (create_options & CREATE_OPTION_SPECIAL)
|
if (create_options & CREATE_OPTION_SPECIAL)
|
||||||
@ -1193,8 +1193,8 @@ openRetry:
|
|||||||
req->AllocationSize = 0;
|
req->AllocationSize = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set file as system file if special file such as fifo and server
|
* Set file as system file if special file such as fifo, socket, char
|
||||||
* expecting SFU style and no Unix extensions.
|
* or block and server expecting SFU style and no Unix extensions.
|
||||||
*/
|
*/
|
||||||
if (create_options & CREATE_OPTION_SPECIAL)
|
if (create_options & CREATE_OPTION_SPECIAL)
|
||||||
req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
|
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 */
|
/* Get Security Descriptor (by handle) from remote server for a file or dir */
|
||||||
int
|
int
|
||||||
CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
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 rc = 0;
|
||||||
int buf_type = 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
|
/* check if buffer is big enough for the acl
|
||||||
header followed by the smallest SID */
|
header followed by the smallest SID */
|
||||||
if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
|
if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||
|
||||||
(*pbuflen >= 64 * 1024)) {
|
(*pbuflen >= 64 * 1024)) {
|
||||||
cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
|
cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
@ -3517,7 +3517,7 @@ qsec_out:
|
|||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
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;
|
__u16 byte_count, param_count, data_count, param_offset, data_offset;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
390
fs/smb/client/compress.c
Normal file
390
fs/smb/client/compress.c
Normal 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
90
fs/smb/client/compress.h
Normal 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 */
|
235
fs/smb/client/compress/lz77.c
Normal file
235
fs/smb/client/compress/lz77.c
Normal 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;
|
||||||
|
}
|
15
fs/smb/client/compress/lz77.h
Normal file
15
fs/smb/client/compress/lz77.h
Normal 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 */
|
@ -1009,11 +1009,10 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!list_empty(&server->pending_mid_q)) {
|
if (!list_empty(&server->pending_mid_q)) {
|
||||||
struct list_head dispose_list;
|
|
||||||
struct mid_q_entry *mid_entry;
|
struct mid_q_entry *mid_entry;
|
||||||
struct list_head *tmp, *tmp2;
|
struct list_head *tmp, *tmp2;
|
||||||
|
LIST_HEAD(dispose_list);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&dispose_list);
|
|
||||||
spin_lock(&server->mid_lock);
|
spin_lock(&server->mid_lock);
|
||||||
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
|
list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
|
||||||
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
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);
|
ses = cifs_get_smb_ses(master_tcon->ses->server, ctx);
|
||||||
if (IS_ERR(ses)) {
|
if (IS_ERR(ses)) {
|
||||||
tcon = (struct cifs_tcon *)ses;
|
tcon = ERR_CAST(ses);
|
||||||
cifs_put_tcp_session(master_tcon->ses->server, 0);
|
cifs_put_tcp_session(master_tcon->ses->server, 0);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1403,7 +1403,7 @@ void
|
|||||||
cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
|
cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
|
||||||
{
|
{
|
||||||
struct cifsFileInfo *open_file, *tmp;
|
struct cifsFileInfo *open_file, *tmp;
|
||||||
struct list_head tmp_list;
|
LIST_HEAD(tmp_list);
|
||||||
|
|
||||||
if (!tcon->use_persistent || !tcon->need_reopen_files)
|
if (!tcon->use_persistent || !tcon->need_reopen_files)
|
||||||
return;
|
return;
|
||||||
@ -1411,7 +1411,6 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
|
|||||||
tcon->need_reopen_files = false;
|
tcon->need_reopen_files = false;
|
||||||
|
|
||||||
cifs_dbg(FYI, "Reopen persistent handles\n");
|
cifs_dbg(FYI, "Reopen persistent handles\n");
|
||||||
INIT_LIST_HEAD(&tmp_list);
|
|
||||||
|
|
||||||
/* list all files open on tree connection, reopen resilient handles */
|
/* list all files open on tree connection, reopen resilient handles */
|
||||||
spin_lock(&tcon->open_file_lock);
|
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 cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
|
||||||
struct cifsLockInfo *li, *tmp;
|
struct cifsLockInfo *li, *tmp;
|
||||||
__u64 length = cifs_flock_len(flock);
|
__u64 length = cifs_flock_len(flock);
|
||||||
struct list_head tmp_llist;
|
LIST_HEAD(tmp_llist);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&tmp_llist);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accessing maxBuf is racy with cifs_reconnect - need to store value
|
* Accessing maxBuf is racy with cifs_reconnect - need to store value
|
||||||
|
@ -978,9 +978,12 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
|||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case Opt_compress:
|
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;
|
ctx->compress = true;
|
||||||
cifs_dbg(VFS,
|
cifs_dbg(VFS, "SMB3 compression support is experimental\n");
|
||||||
"SMB3 compression support is experimental\n");
|
|
||||||
break;
|
break;
|
||||||
case Opt_nodfs:
|
case Opt_nodfs:
|
||||||
ctx->nodfs = 1;
|
ctx->nodfs = 1;
|
||||||
@ -1896,14 +1899,17 @@ void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
|
|||||||
if (ctx->mfsymlinks) {
|
if (ctx->mfsymlinks) {
|
||||||
if (ctx->sfu_emul) {
|
if (ctx->sfu_emul) {
|
||||||
/*
|
/*
|
||||||
* Our SFU ("Services for Unix" emulation does not allow
|
* Our SFU ("Services for Unix") emulation allows now
|
||||||
* creating symlinks but does allow reading existing SFU
|
* creating new and reading existing SFU symlinks.
|
||||||
* symlinks (it does allow both creating and reading SFU
|
* Older Linux kernel versions were not able to neither
|
||||||
* style mknod and FIFOs though). When "mfsymlinks" and
|
* 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
|
* "sfu" are both enabled at the same time, it allows
|
||||||
* reading both types of symlinks, but will only create
|
* reading both types of symlinks, but will only create
|
||||||
* them with mfsymlinks format. This allows better
|
* 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.
|
* while still recognizing old Windows style symlinks.
|
||||||
*/
|
*/
|
||||||
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
|
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
|
||||||
|
@ -529,6 +529,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
|||||||
struct cifs_fid fid;
|
struct cifs_fid fid;
|
||||||
struct cifs_open_parms oparms;
|
struct cifs_open_parms oparms;
|
||||||
struct cifs_io_parms io_parms = {0};
|
struct cifs_io_parms io_parms = {0};
|
||||||
|
char *symlink_buf_utf16;
|
||||||
|
unsigned int symlink_len_utf16;
|
||||||
char buf[24];
|
char buf[24];
|
||||||
unsigned int bytes_read;
|
unsigned int bytes_read;
|
||||||
char *pbuf;
|
char *pbuf;
|
||||||
@ -539,10 +541,11 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
|||||||
fattr->cf_mode &= ~S_IFMT;
|
fattr->cf_mode &= ~S_IFMT;
|
||||||
|
|
||||||
if (fattr->cf_eof == 0) {
|
if (fattr->cf_eof == 0) {
|
||||||
|
cifs_dbg(FYI, "Fifo\n");
|
||||||
fattr->cf_mode |= S_IFIFO;
|
fattr->cf_mode |= S_IFIFO;
|
||||||
fattr->cf_dtype = DT_FIFO;
|
fattr->cf_dtype = DT_FIFO;
|
||||||
return 0;
|
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_mode |= S_IFREG;
|
||||||
fattr->cf_dtype = DT_REG;
|
fattr->cf_dtype = DT_REG;
|
||||||
return -EINVAL; /* EOPNOTSUPP? */
|
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,
|
rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
|
||||||
&bytes_read, &pbuf, &buf_type);
|
&bytes_read, &pbuf, &buf_type);
|
||||||
if ((rc == 0) && (bytes_read >= 8)) {
|
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");
|
cifs_dbg(FYI, "Block device\n");
|
||||||
fattr->cf_mode |= S_IFBLK;
|
fattr->cf_mode |= S_IFBLK;
|
||||||
fattr->cf_dtype = DT_BLK;
|
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));
|
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||||
fattr->cf_rdev = MKDEV(mjr, mnr);
|
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");
|
cifs_dbg(FYI, "Char device\n");
|
||||||
fattr->cf_mode |= S_IFCHR;
|
fattr->cf_mode |= S_IFCHR;
|
||||||
fattr->cf_dtype = DT_CHR;
|
fattr->cf_dtype = DT_CHR;
|
||||||
@ -612,10 +615,37 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
|||||||
cifs_dbg(FYI, "Socket\n");
|
cifs_dbg(FYI, "Socket\n");
|
||||||
fattr->cf_mode |= S_IFSOCK;
|
fattr->cf_mode |= S_IFSOCK;
|
||||||
fattr->cf_dtype = DT_SOCK;
|
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");
|
cifs_dbg(FYI, "Symlink\n");
|
||||||
fattr->cf_mode |= S_IFLNK;
|
fattr->cf_mode |= S_IFLNK;
|
||||||
fattr->cf_dtype = DT_LNK;
|
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) {
|
} else if (memcmp("LnxFIFO", pbuf, 8) == 0) {
|
||||||
cifs_dbg(FYI, "FIFO\n");
|
cifs_dbg(FYI, "FIFO\n");
|
||||||
fattr->cf_mode |= S_IFIFO;
|
fattr->cf_mode |= S_IFIFO;
|
||||||
@ -625,6 +655,10 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
|||||||
fattr->cf_dtype = DT_REG;
|
fattr->cf_dtype = DT_REG;
|
||||||
rc = -EOPNOTSUPP;
|
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 {
|
} else {
|
||||||
fattr->cf_mode |= S_IFREG; /* then it is a file */
|
fattr->cf_mode |= S_IFREG; /* then it is a file */
|
||||||
fattr->cf_dtype = DT_REG;
|
fattr->cf_dtype = DT_REG;
|
||||||
|
@ -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 */
|
/* BB what if DFS and this volume is on different share? BB */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
|
||||||
rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
|
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
|
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||||
} else if (pTcon->unix_ext) {
|
} else if (pTcon->unix_ext) {
|
||||||
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
||||||
|
@ -751,12 +751,11 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
|
|||||||
{
|
{
|
||||||
struct cifsFileInfo *cfile = NULL;
|
struct cifsFileInfo *cfile = NULL;
|
||||||
struct file_list *tmp_list, *tmp_next_list;
|
struct file_list *tmp_list, *tmp_next_list;
|
||||||
struct list_head file_head;
|
LIST_HEAD(file_head);
|
||||||
|
|
||||||
if (cifs_inode == NULL)
|
if (cifs_inode == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&file_head);
|
|
||||||
spin_lock(&cifs_inode->open_file_lock);
|
spin_lock(&cifs_inode->open_file_lock);
|
||||||
list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
|
list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
|
||||||
if (delayed_work_pending(&cfile->deferred)) {
|
if (delayed_work_pending(&cfile->deferred)) {
|
||||||
@ -787,9 +786,8 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
|||||||
{
|
{
|
||||||
struct cifsFileInfo *cfile;
|
struct cifsFileInfo *cfile;
|
||||||
struct file_list *tmp_list, *tmp_next_list;
|
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);
|
spin_lock(&tcon->open_file_lock);
|
||||||
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
||||||
if (delayed_work_pending(&cfile->deferred)) {
|
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 cifsFileInfo *cfile;
|
||||||
struct file_list *tmp_list, *tmp_next_list;
|
struct file_list *tmp_list, *tmp_next_list;
|
||||||
struct list_head file_head;
|
|
||||||
void *page;
|
void *page;
|
||||||
const char *full_path;
|
const char *full_path;
|
||||||
|
LIST_HEAD(file_head);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&file_head);
|
|
||||||
page = alloc_dentry_path();
|
page = alloc_dentry_path();
|
||||||
spin_lock(&tcon->open_file_lock);
|
spin_lock(&tcon->open_file_lock);
|
||||||
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
||||||
|
@ -1078,7 +1078,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
|
|||||||
/*
|
/*
|
||||||
* Check if mounted with mount parm 'sfu' mount parm.
|
* Check if mounted with mount parm 'sfu' mount parm.
|
||||||
* SFU emulation should work with all servers, but only
|
* 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
|
* and was used by default in earlier versions of Windows
|
||||||
*/
|
*/
|
||||||
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
|
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "fscache.h"
|
#include "fscache.h"
|
||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
|
|
||||||
static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)
|
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 cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
|
||||||
struct cifsLockInfo *li, *tmp;
|
struct cifsLockInfo *li, *tmp;
|
||||||
__u64 length = 1 + flock->fl_end - flock->fl_start;
|
__u64 length = 1 + flock->fl_end - flock->fl_start;
|
||||||
struct list_head tmp_llist;
|
LIST_HEAD(tmp_llist);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&tmp_llist);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Accessing maxBuf is racy with cifs_reconnect - need to store value
|
* Accessing maxBuf is racy with cifs_reconnect - need to store value
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "smb2pdu.h"
|
#include "smb2pdu.h"
|
||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
#include "cached_dir.h"
|
#include "cached_dir.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
|
|
||||||
static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
|
static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
|
||||||
{
|
{
|
||||||
@ -315,7 +315,7 @@ replay_again:
|
|||||||
SMB2_O_INFO_FILE, 0,
|
SMB2_O_INFO_FILE, 0,
|
||||||
sizeof(struct smb311_posix_qinfo *) +
|
sizeof(struct smb311_posix_qinfo *) +
|
||||||
(PATH_MAX * 2) +
|
(PATH_MAX * 2) +
|
||||||
(sizeof(struct cifs_sid) * 2), 0, NULL);
|
(sizeof(struct smb_sid) * 2), 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
rc = SMB2_query_info_init(tcon, server,
|
rc = SMB2_query_info_init(tcon, server,
|
||||||
&rqst[num_rqst],
|
&rqst[num_rqst],
|
||||||
@ -325,7 +325,7 @@ replay_again:
|
|||||||
SMB2_O_INFO_FILE, 0,
|
SMB2_O_INFO_FILE, 0,
|
||||||
sizeof(struct smb311_posix_qinfo *) +
|
sizeof(struct smb311_posix_qinfo *) +
|
||||||
(PATH_MAX * 2) +
|
(PATH_MAX * 2) +
|
||||||
(sizeof(struct cifs_sid) * 2), 0, NULL);
|
(sizeof(struct smb_sid) * 2), 0, NULL);
|
||||||
}
|
}
|
||||||
if (!rc && (!cfile || num_rqst > 1)) {
|
if (!rc && (!cfile || num_rqst > 1)) {
|
||||||
smb2_set_next_command(tcon, &rqst[num_rqst]);
|
smb2_set_next_command(tcon, &rqst[num_rqst]);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "smb2pdu.h"
|
#include "smb2pdu.h"
|
||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
#include "smb2glob.h"
|
#include "smb2glob.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
#include "smb2glob.h"
|
#include "smb2glob.h"
|
||||||
#include "nterr.h"
|
#include "nterr.h"
|
||||||
#include "cached_dir.h"
|
#include "cached_dir.h"
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "cifsproto.h"
|
#include "cifsproto.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
#include "smb2glob.h"
|
#include "smb2glob.h"
|
||||||
#include "cifs_ioctl.h"
|
#include "cifs_ioctl.h"
|
||||||
#include "smbdirect.h"
|
#include "smbdirect.h"
|
||||||
@ -3050,11 +3050,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cifs_ntsd *
|
static struct smb_ntsd *
|
||||||
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
||||||
const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
|
const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int rc = -EOPNOTSUPP;
|
int rc = -EOPNOTSUPP;
|
||||||
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
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,
|
get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
|
||||||
const char *path, u32 *pacllen, u32 info)
|
const char *path, u32 *pacllen, u32 info)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
int rc;
|
int rc;
|
||||||
@ -3146,7 +3146,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
struct inode *inode, const char *path, int aclflag)
|
||||||
{
|
{
|
||||||
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
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 */
|
/* Retrieve an ACL from the server */
|
||||||
static struct cifs_ntsd *
|
static struct smb_ntsd *
|
||||||
get_smb2_acl(struct cifs_sb_info *cifs_sb,
|
get_smb2_acl(struct cifs_sb_info *cifs_sb,
|
||||||
struct inode *inode, const char *path,
|
struct inode *inode, const char *path,
|
||||||
u32 *pacllen, u32 info)
|
u32 *pacllen, u32 info)
|
||||||
{
|
{
|
||||||
struct cifs_ntsd *pntsd = NULL;
|
struct smb_ntsd *pntsd = NULL;
|
||||||
struct cifsFileInfo *open_file = NULL;
|
struct cifsFileInfo *open_file = NULL;
|
||||||
|
|
||||||
if (inode && !(info & SACL_SECINFO))
|
if (inode && !(info & SACL_SECINFO))
|
||||||
@ -5078,9 +5078,10 @@ static int smb2_next_header(struct TCP_Server_Info *server, char *buf,
|
|||||||
return 0;
|
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,
|
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 TCP_Server_Info *server = tcon->ses->server;
|
||||||
struct cifs_open_parms oparms;
|
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_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
struct cifs_fid fid;
|
struct cifs_fid fid;
|
||||||
unsigned int bytes_written;
|
unsigned int bytes_written;
|
||||||
struct win_dev pdev = {};
|
u8 type[8];
|
||||||
struct kvec iov[2];
|
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;
|
__u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
switch (mode & S_IFMT) {
|
switch (mode & S_IFMT) {
|
||||||
case S_IFCHR:
|
case S_IFCHR:
|
||||||
strscpy(pdev.type, "IntxCHR");
|
type_len = 8;
|
||||||
|
memcpy(type, "IntxCHR\0", type_len);
|
||||||
pdev.major = cpu_to_le64(MAJOR(dev));
|
pdev.major = cpu_to_le64(MAJOR(dev));
|
||||||
pdev.minor = cpu_to_le64(MINOR(dev));
|
pdev.minor = cpu_to_le64(MINOR(dev));
|
||||||
|
data = (u8 *)&pdev;
|
||||||
|
data_len = sizeof(pdev);
|
||||||
break;
|
break;
|
||||||
case S_IFBLK:
|
case S_IFBLK:
|
||||||
strscpy(pdev.type, "IntxBLK");
|
type_len = 8;
|
||||||
|
memcpy(type, "IntxBLK\0", type_len);
|
||||||
pdev.major = cpu_to_le64(MAJOR(dev));
|
pdev.major = cpu_to_le64(MAJOR(dev));
|
||||||
pdev.minor = cpu_to_le64(MINOR(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;
|
break;
|
||||||
case S_IFSOCK:
|
case S_IFSOCK:
|
||||||
strscpy(pdev.type, "LnxSOCK");
|
type_len = 8;
|
||||||
|
strscpy(type, "LnxSOCK");
|
||||||
|
data = (u8 *)&pdev;
|
||||||
|
data_len = sizeof(pdev);
|
||||||
break;
|
break;
|
||||||
case S_IFIFO:
|
case S_IFIFO:
|
||||||
strscpy(pdev.type, "LnxFIFO");
|
type_len = 8;
|
||||||
|
strscpy(type, "LnxFIFO");
|
||||||
|
data = (u8 *)&pdev;
|
||||||
|
data_len = sizeof(pdev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EPERM;
|
rc = -EPERM;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE,
|
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);
|
rc = server->ops->open(xid, &oparms, &oplock, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
goto out;
|
||||||
|
|
||||||
io_parms.pid = current->tgid;
|
if (type_len + data_len > 0) {
|
||||||
io_parms.tcon = tcon;
|
io_parms.pid = current->tgid;
|
||||||
io_parms.length = sizeof(pdev);
|
io_parms.tcon = tcon;
|
||||||
iov[1].iov_base = &pdev;
|
io_parms.length = type_len + data_len;
|
||||||
iov[1].iov_len = sizeof(pdev);
|
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, ARRAY_SIZE(iov)-1);
|
||||||
|
}
|
||||||
|
|
||||||
rc = server->ops->sync_write(xid, &fid, &io_parms,
|
|
||||||
&bytes_written, iov, 1);
|
|
||||||
server->ops->close(xid, tcon, &fid);
|
server->ops->close(xid, tcon, &fid);
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(symname_utf16);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5143,7 +5187,7 @@ int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = __cifs_sfu_make_node(xid, inode, dentry, tcon,
|
rc = __cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||||
full_path, mode, dev);
|
full_path, mode, dev, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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.
|
* Check if mounted with mount parm 'sfu' mount parm.
|
||||||
* SFU emulation should work with all servers, but only
|
* 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
|
* and was used by default in earlier versions of Windows
|
||||||
*/
|
*/
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include "cifs_unicode.h"
|
#include "cifs_unicode.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "ntlmssp.h"
|
#include "ntlmssp.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
#include "smb2glob.h"
|
#include "smb2glob.h"
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#include "cifs_spnego.h"
|
#include "cifs_spnego.h"
|
||||||
@ -42,6 +42,7 @@
|
|||||||
#include "dfs_cache.h"
|
#include "dfs_cache.h"
|
||||||
#endif
|
#endif
|
||||||
#include "cached_dir.h"
|
#include "cached_dir.h"
|
||||||
|
#include "compress.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following table defines the expected "StructureSize" of SMB2 requests
|
* 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;
|
unsigned int group_offset = 0;
|
||||||
struct smb3_acl acl = {};
|
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) {
|
if (set_owner) {
|
||||||
/* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
|
/* 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);
|
ptr += sizeof(struct smb3_acl);
|
||||||
|
|
||||||
/* create one ACE to hold the mode embedded in reserved special SID */
|
/* 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;
|
ptr += acelen;
|
||||||
acl_size = acelen + sizeof(struct smb3_acl);
|
acl_size = acelen + sizeof(struct smb3_acl);
|
||||||
ace_count = 1;
|
ace_count = 1;
|
||||||
|
|
||||||
if (set_owner) {
|
if (set_owner) {
|
||||||
/* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
|
/* 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;
|
ptr += acelen;
|
||||||
acl_size += acelen;
|
acl_size += acelen;
|
||||||
ace_count += 1;
|
ace_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and one more ACE to allow access for authenticated users */
|
/* 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;
|
ptr += acelen;
|
||||||
acl_size += acelen;
|
acl_size += acelen;
|
||||||
ace_count += 1;
|
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)
|
u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
|
||||||
{
|
{
|
||||||
size_t output_len = sizeof(struct smb311_posix_qinfo *) +
|
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;
|
*plen = 0;
|
||||||
|
|
||||||
return query_info(xid, tcon, persistent_fid, volatile_fid,
|
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;
|
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,
|
rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
|
||||||
wdata, flags, &wdata->credits);
|
wdata, flags, &wdata->credits);
|
||||||
/* Can't touch wdata if rc == 0 */
|
/* 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
|
int
|
||||||
SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_fid, u64 volatile_fid,
|
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,
|
return send_set_info(xid, tcon, persistent_fid, volatile_fid,
|
||||||
current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
|
current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
|
||||||
|
@ -364,8 +364,8 @@ struct create_posix_rsp {
|
|||||||
u32 nlink;
|
u32 nlink;
|
||||||
u32 reparse_tag;
|
u32 reparse_tag;
|
||||||
u32 mode;
|
u32 mode;
|
||||||
struct cifs_sid owner; /* var-sized on the wire */
|
struct smb_sid owner; /* var-sized on the wire */
|
||||||
struct cifs_sid group; /* var-sized on the wire */
|
struct smb_sid group; /* var-sized on the wire */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2
|
#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2
|
||||||
@ -408,8 +408,8 @@ struct smb2_posix_info {
|
|||||||
struct smb2_posix_info_parsed {
|
struct smb2_posix_info_parsed {
|
||||||
const struct smb2_posix_info *base;
|
const struct smb2_posix_info *base;
|
||||||
size_t size;
|
size_t size;
|
||||||
struct cifs_sid owner;
|
struct smb_sid owner;
|
||||||
struct cifs_sid group;
|
struct smb_sid group;
|
||||||
int name_len;
|
int name_len;
|
||||||
const u8 *name;
|
const u8 *name;
|
||||||
};
|
};
|
||||||
|
@ -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 void SMB2_set_info_free(struct smb_rqst *rqst);
|
||||||
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_fid, u64 volatile_fid,
|
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,
|
extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_fid, u64 volatile_fid,
|
u64 persistent_fid, u64 volatile_fid,
|
||||||
struct smb2_file_full_ea_info *buf, int len);
|
struct smb2_file_full_ea_info *buf, int len);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "cifsproto.h"
|
#include "cifsproto.h"
|
||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "smb2status.h"
|
#include "../common/smb2status.h"
|
||||||
#include "smb2glob.h"
|
#include "smb2glob.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1586,10 +1586,8 @@ static struct smbd_connection *_smbd_get_connection(
|
|||||||
conn_param.initiator_depth = 0;
|
conn_param.initiator_depth = 0;
|
||||||
|
|
||||||
conn_param.responder_resources =
|
conn_param.responder_resources =
|
||||||
info->id->device->attrs.max_qp_rd_atom
|
min(info->id->device->attrs.max_qp_rd_atom,
|
||||||
< SMBD_CM_RESPONDER_RESOURCES ?
|
SMBD_CM_RESPONDER_RESOURCES);
|
||||||
info->id->device->attrs.max_qp_rd_atom :
|
|
||||||
SMBD_CM_RESPONDER_RESOURCES;
|
|
||||||
info->responder_resources = conn_param.responder_resources;
|
info->responder_resources = conn_param.responder_resources;
|
||||||
log_rdma_mr(INFO, "responder_resources=%d\n",
|
log_rdma_mr(INFO, "responder_resources=%d\n",
|
||||||
info->responder_resources);
|
info->responder_resources);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "cifs_debug.h"
|
#include "cifs_debug.h"
|
||||||
#include "smb2proto.h"
|
#include "smb2proto.h"
|
||||||
#include "smbdirect.h"
|
#include "smbdirect.h"
|
||||||
|
#include "compress.h"
|
||||||
|
|
||||||
/* Max number of iovectors we can use off the stack when sending requests. */
|
/* Max number of iovectors we can use off the stack when sending requests. */
|
||||||
#define CIFS_MAX_IOV_SIZE 8
|
#define CIFS_MAX_IOV_SIZE 8
|
||||||
@ -432,6 +433,9 @@ smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
|
|||||||
struct kvec *iov;
|
struct kvec *iov;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (flags & CIFS_COMPRESS_REQ)
|
||||||
|
return smb_compress(server, &rqst[0], __smb_send_rqst);
|
||||||
|
|
||||||
if (!(flags & CIFS_TRANSFORM_REQ))
|
if (!(flags & CIFS_TRANSFORM_REQ))
|
||||||
return __smb_send_rqst(server, num_rqst, rqst);
|
return __smb_send_rqst(server, num_rqst, rqst);
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
|||||||
case XATTR_CIFS_ACL:
|
case XATTR_CIFS_ACL:
|
||||||
case XATTR_CIFS_NTSD:
|
case XATTR_CIFS_NTSD:
|
||||||
case XATTR_CIFS_NTSD_FULL: {
|
case XATTR_CIFS_NTSD_FULL: {
|
||||||
struct cifs_ntsd *pacl;
|
struct smb_ntsd *pacl;
|
||||||
|
|
||||||
if (!value)
|
if (!value)
|
||||||
goto out;
|
goto out;
|
||||||
@ -315,7 +315,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
|||||||
* fetch owner and DACL otherwise
|
* fetch owner and DACL otherwise
|
||||||
*/
|
*/
|
||||||
u32 acllen, extra_info;
|
u32 acllen, extra_info;
|
||||||
struct cifs_ntsd *pacl;
|
struct smb_ntsd *pacl;
|
||||||
|
|
||||||
if (pTcon->ses->server->ops->get_acl == NULL)
|
if (pTcon->ses->server->ops->get_acl == NULL)
|
||||||
goto out; /* rc already EOPNOTSUPP */
|
goto out; /* rc already EOPNOTSUPP */
|
||||||
|
@ -901,6 +901,10 @@ struct ntstatus {
|
|||||||
#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
|
#define STATUS_DEVICE_ENUMERATION_ERROR cpu_to_le32(0xC0000366)
|
||||||
#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
|
#define STATUS_MOUNT_POINT_NOT_RESOLVED cpu_to_le32(0xC0000368)
|
||||||
#define STATUS_INVALID_DEVICE_OBJECT_PARAMETER cpu_to_le32(0xC0000369)
|
#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_MCA_OCCURED cpu_to_le32(0xC000036A)
|
||||||
#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
|
#define STATUS_DRIVER_BLOCKED_CRITICAL cpu_to_le32(0xC000036B)
|
||||||
#define STATUS_DRIVER_BLOCKED cpu_to_le32(0xC000036C)
|
#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_INVALID_PACKET cpu_to_le32(0xC0360005)
|
||||||
#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
|
#define STATUS_IPSEC_INTEGRITY_CHECK_FAILED cpu_to_le32(0xC0360006)
|
||||||
#define STATUS_IPSEC_CLEAR_TEXT_DROP cpu_to_le32(0xC0360007)
|
#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
121
fs/smb/common/smbacl.h
Normal 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 */
|
@ -10,7 +10,7 @@
|
|||||||
#include "oplock.h"
|
#include "oplock.h"
|
||||||
|
|
||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "smbstatus.h"
|
#include "../common/smb2status.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "mgmt/user_session.h"
|
#include "mgmt/user_session.h"
|
||||||
#include "mgmt/share_config.h"
|
#include "mgmt/share_config.h"
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "smbstatus.h"
|
#include "../common/smb2status.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "transport_ipc.h"
|
#include "transport_ipc.h"
|
||||||
#include "mgmt/user_session.h"
|
#include "mgmt/user_session.h"
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "glob.h"
|
#include "glob.h"
|
||||||
#include "nterr.h"
|
#include "nterr.h"
|
||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "smbstatus.h"
|
#include "../common/smb2status.h"
|
||||||
#include "mgmt/user_session.h"
|
#include "mgmt/user_session.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "smbstatus.h"
|
#include "../common/smb2status.h"
|
||||||
#include "ksmbd_work.h"
|
#include "ksmbd_work.h"
|
||||||
#include "mgmt/user_config.h"
|
#include "mgmt/user_config.h"
|
||||||
#include "mgmt/share_config.h"
|
#include "mgmt/share_config.h"
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "smbstatus.h"
|
#include "../common/smb2status.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "ksmbd_work.h"
|
#include "ksmbd_work.h"
|
||||||
#include "mgmt/user_session.h"
|
#include "mgmt/user_session.h"
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#ifndef _SMBACL_H
|
#ifndef _SMBACL_H
|
||||||
#define _SMBACL_H
|
#define _SMBACL_H
|
||||||
|
|
||||||
|
#include "../common/smbacl.h"
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/posix_acl.h>
|
#include <linux/posix_acl.h>
|
||||||
@ -15,32 +16,6 @@
|
|||||||
|
|
||||||
#include "mgmt/tree_connect.h"
|
#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 */
|
/* Revision for ACLs */
|
||||||
#define SD_REVISION 1
|
#define SD_REVISION 1
|
||||||
|
|
||||||
@ -62,92 +37,8 @@ enum {
|
|||||||
#define RM_CONTROL_VALID 0x4000
|
#define RM_CONTROL_VALID 0x4000
|
||||||
#define SELF_RELATIVE 0x8000
|
#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 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 {
|
struct smb_fattr {
|
||||||
kuid_t cf_uid;
|
kuid_t cf_uid;
|
||||||
kgid_t cf_gid;
|
kgid_t cf_gid;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
|||||||
#include "glob.h"
|
#include "glob.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "smb_common.h"
|
#include "smb_common.h"
|
||||||
#include "smbstatus.h"
|
#include "../common/smb2status.h"
|
||||||
#include "transport_rdma.h"
|
#include "transport_rdma.h"
|
||||||
|
|
||||||
#define SMB_DIRECT_PORT_IWARP 5445
|
#define SMB_DIRECT_PORT_IWARP 5445
|
||||||
|
Loading…
Reference in New Issue
Block a user