13 cifs/smb3 client fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmObnuoACgkQiiy9cAdy T1GD2Av8CsAWbrFNa5blTrtbZcEN5bkllLN2HC2BbCHFiFHcRWLCctEjfq7SlvZR 5JKgUL00mT4qAwGsjmfvHlqM1MFCwx27EoVMRZwYrEOnJKvHbX4VF/G74XSJHIdI 0zPtBblJq0l8AautwBwrI3OxO1u2WYR7P/mCi9/AxXxgGRgZDXIprjEX+A2w+FwG oi9w2BJo2LX/3STEPRjgblIrIqU1iu9tSvEoMsjeFn+yCk5IqeII0P+TPcLcNRFd kdQcTkjcj1yAZqhnXr7xpnimIwliXTxC4eCytJTDVMSJ9B08f4mOpM8JLfi4VyNr hT9Y3C97+7FfYthP7d31ubMt6WonoujW8s4bSQ6hNoQDLhfoNClWEzv5HNyYxQDZ 2dGzY+zwpbAnwZ/b8I/6xT46Xl+RutJ9TsLtN1q45RtdoNvomcby4PLccOgH2vGy hIe3kBozV0yD/CsOA5bIMFR4rNXXmq9oHyMDUrv6xKcoAQAD65PiY3GredrT+BI0 6CaVK/v5 =Ufyp -----END PGP SIGNATURE----- Merge tag '6.2-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6 Pull cifs client updates from Steve French: - SMB3.1.1 POSIX Extensions fixes - remove use of generic_writepages() and ->cifs_writepage(), in favor of ->cifs_writepages() and ->migrate_folio() - memory management fixes - mount parm parsing fixes - minor cleanup fixes * tag '6.2-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: cifs: Remove duplicated include in cifsglob.h cifs: fix oops during encryption cifs: print warning when conflicting soft vs. hard mount options specified cifs: fix missing display of three mount options cifs: fix various whitespace errors in headers cifs: minor cleanup of some headers cifs: skip alloc when request has no pages cifs: remove ->writepage cifs: stop using generic_writepages cifs: wire up >migrate_folio cifs: Parse owner/group for stat in smb311 posix extensions cifs: Add "extbuf" and "extbuflen" args to smb2_compound_op() Fix path in cifs/usage.rst
This commit is contained in:
commit
851f657a86
|
@ -858,7 +858,7 @@ CIFS kernel module parameters
|
|||
These module parameters can be specified or modified either during the time of
|
||||
module loading or during the runtime by using the interface::
|
||||
|
||||
/proc/module/cifs/parameters/<param>
|
||||
/sys/module/cifs/parameters/<param>
|
||||
|
||||
i.e.::
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ struct smb3_notify_info {
|
|||
#define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify)
|
||||
#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
|
||||
#define CIFS_IOC_NOTIFY_INFO _IOWR(CIFS_IOCTL_MAGIC, 11, struct smb3_notify_info)
|
||||
#define CIFS_IOC_SHUTDOWN _IOR ('X', 125, __u32)
|
||||
#define CIFS_IOC_SHUTDOWN _IOR('X', 125, __u32)
|
||||
|
||||
/*
|
||||
* Flags for going down operation
|
||||
|
|
|
@ -678,9 +678,15 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
|||
seq_printf(s, ",echo_interval=%lu",
|
||||
tcon->ses->server->echo_interval / HZ);
|
||||
|
||||
/* Only display max_credits if it was overridden on mount */
|
||||
/* Only display the following if overridden on mount */
|
||||
if (tcon->ses->server->max_credits != SMB2_MAX_CREDITS_AVAILABLE)
|
||||
seq_printf(s, ",max_credits=%u", tcon->ses->server->max_credits);
|
||||
if (tcon->ses->server->tcp_nodelay)
|
||||
seq_puts(s, ",tcpnodelay");
|
||||
if (tcon->ses->server->noautotune)
|
||||
seq_puts(s, ",noautotune");
|
||||
if (tcon->ses->server->noblocksnd)
|
||||
seq_puts(s, ",noblocksend");
|
||||
|
||||
if (tcon->snapshot_time)
|
||||
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
|
||||
|
|
|
@ -105,8 +105,8 @@ extern int cifs_lock(struct file *, int, struct file_lock *);
|
|||
extern int cifs_fsync(struct file *, loff_t, loff_t, int);
|
||||
extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int);
|
||||
extern int cifs_flush(struct file *, fl_owner_t id);
|
||||
extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
|
||||
extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
|
||||
extern int cifs_file_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
extern int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
extern const struct file_operations cifs_dir_ops;
|
||||
extern int cifs_dir_open(struct inode *inode, struct file *file);
|
||||
extern int cifs_readdir(struct file *file, struct dir_context *ctx);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <linux/in6.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/utsname.h>
|
||||
|
@ -21,7 +23,6 @@
|
|||
#include "cifs_fs_sb.h"
|
||||
#include "cifsacl.h"
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <uapi/linux/cifs/cifs_mount.h>
|
||||
#include "../smbfs_common/smb2pdu.h"
|
||||
#include "smb2pdu.h"
|
||||
|
@ -785,6 +786,7 @@ static inline unsigned int
|
|||
in_flight(struct TCP_Server_Info *server)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
spin_lock(&server->req_lock);
|
||||
num = server->in_flight;
|
||||
spin_unlock(&server->req_lock);
|
||||
|
@ -795,6 +797,7 @@ static inline bool
|
|||
has_credits(struct TCP_Server_Info *server, int *credits, int num_credits)
|
||||
{
|
||||
int num;
|
||||
|
||||
spin_lock(&server->req_lock);
|
||||
num = *credits;
|
||||
spin_unlock(&server->req_lock);
|
||||
|
@ -1025,7 +1028,7 @@ struct cifs_ses {
|
|||
struct TCP_Server_Info *server; /* pointer to server info */
|
||||
int ses_count; /* reference counter */
|
||||
enum ses_status_enum ses_status; /* updates protected by cifs_tcp_ses_lock */
|
||||
unsigned overrideSecFlg; /* if non-zero override global sec flags */
|
||||
unsigned int overrideSecFlg; /* if non-zero override global sec flags */
|
||||
char *serverOS; /* name of operating system underlying server */
|
||||
char *serverNOS; /* name of network operating system of server */
|
||||
char *serverDomain; /* security realm of server */
|
||||
|
@ -1381,7 +1384,7 @@ struct cifsFileInfo {
|
|||
__u32 pid; /* process id who opened file */
|
||||
struct cifs_fid fid; /* file id from remote */
|
||||
struct list_head rlist; /* reconnect list */
|
||||
/* BB add lock scope info here if needed */ ;
|
||||
/* BB add lock scope info here if needed */
|
||||
/* lock scope id (0 if none) */
|
||||
struct dentry *dentry;
|
||||
struct tcon_link *tlink;
|
||||
|
@ -1769,6 +1772,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
|
|||
int number_of_items)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((number_of_items == 0) || (param == NULL))
|
||||
return;
|
||||
for (i = 0; i < number_of_items; i++) {
|
||||
|
@ -2137,4 +2141,70 @@ static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const
|
|||
dst->FileNameLength = src->FileNameLength;
|
||||
}
|
||||
|
||||
static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst,
|
||||
int num_rqst,
|
||||
const u8 *sig)
|
||||
{
|
||||
unsigned int len, skip;
|
||||
unsigned int nents = 0;
|
||||
unsigned long addr;
|
||||
int i, j;
|
||||
|
||||
/* Assumes the first rqst has a transform header as the first iov.
|
||||
* I.e.
|
||||
* rqst[0].rq_iov[0] is transform header
|
||||
* rqst[0].rq_iov[1+] data to be encrypted/decrypted
|
||||
* rqst[1+].rq_iov[0+] data to be encrypted/decrypted
|
||||
*/
|
||||
for (i = 0; i < num_rqst; i++) {
|
||||
/*
|
||||
* The first rqst has a transform header where the
|
||||
* first 20 bytes are not part of the encrypted blob.
|
||||
*/
|
||||
for (j = 0; j < rqst[i].rq_nvec; j++) {
|
||||
struct kvec *iov = &rqst[i].rq_iov[j];
|
||||
|
||||
skip = (i == 0) && (j == 0) ? 20 : 0;
|
||||
addr = (unsigned long)iov->iov_base + skip;
|
||||
if (unlikely(is_vmalloc_addr((void *)addr))) {
|
||||
len = iov->iov_len - skip;
|
||||
nents += DIV_ROUND_UP(offset_in_page(addr) + len,
|
||||
PAGE_SIZE);
|
||||
} else {
|
||||
nents++;
|
||||
}
|
||||
}
|
||||
nents += rqst[i].rq_npages;
|
||||
}
|
||||
nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
|
||||
return nents;
|
||||
}
|
||||
|
||||
/* We can not use the normal sg_set_buf() as we will sometimes pass a
|
||||
* stack object as buf.
|
||||
*/
|
||||
static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg,
|
||||
const void *buf,
|
||||
unsigned int buflen)
|
||||
{
|
||||
unsigned long addr = (unsigned long)buf;
|
||||
unsigned int off = offset_in_page(addr);
|
||||
|
||||
addr &= PAGE_MASK;
|
||||
if (unlikely(is_vmalloc_addr((void *)addr))) {
|
||||
do {
|
||||
unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);
|
||||
|
||||
sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off);
|
||||
|
||||
off = 0;
|
||||
addr += PAGE_SIZE;
|
||||
buflen -= len;
|
||||
} while (buflen);
|
||||
} else {
|
||||
sg_set_page(sg++, virt_to_page(addr), buflen, off);
|
||||
}
|
||||
return sg;
|
||||
}
|
||||
|
||||
#endif /* _CIFS_GLOB_H */
|
||||
|
|
|
@ -1429,7 +1429,7 @@ typedef struct smb_com_transaction_change_notify_req {
|
|||
__u8 WatchTree; /* 1 = Monitor subdirectories */
|
||||
__u8 Reserved2;
|
||||
__le16 ByteCount;
|
||||
/* __u8 Pad[3];*/
|
||||
/* __u8 Pad[3];*/
|
||||
/* __u8 Data[1];*/
|
||||
} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
|
||||
|
||||
|
@ -1752,8 +1752,7 @@ struct smb_com_transaction2_sfi_rsp {
|
|||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__u16 ByteCount;
|
||||
__u16 Reserved2; /* parameter word reserved -
|
||||
present for infolevels > 100 */
|
||||
__u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct smb_t2_qfi_req {
|
||||
|
@ -1768,8 +1767,7 @@ struct smb_t2_qfi_rsp {
|
|||
struct smb_hdr hdr; /* wct = 10 + SetupCount */
|
||||
struct trans2_resp t2;
|
||||
__u16 ByteCount;
|
||||
__u16 Reserved2; /* parameter word reserved -
|
||||
present for infolevels > 100 */
|
||||
__u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
|
@ -2146,13 +2144,11 @@ typedef struct {
|
|||
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
|
||||
calls including posix open
|
||||
and posix unlink */
|
||||
#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
|
||||
to 0xFFFF00 */
|
||||
#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up to 0xFFFF00 */
|
||||
#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
|
||||
#define CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP 0x00000100 /* can do SPNEGO crypt */
|
||||
#define CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP 0x00000200 /* must do */
|
||||
#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and
|
||||
QFS PROXY call */
|
||||
#define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and QFS PROXY call */
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
/* presumably don't need the 0x20 POSIX_PATH_OPS_CAP since we never send
|
||||
LockingX instead of posix locking call on unix sess (and we do not expect
|
||||
|
@ -2368,8 +2364,7 @@ typedef struct {
|
|||
|
||||
struct file_allocation_info {
|
||||
__le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
|
||||
} __attribute__((packed)); /* size used on disk, for level 0x103 for set,
|
||||
0x105 for query */
|
||||
} __packed; /* size used on disk, for level 0x103 for set, 0x105 for query */
|
||||
|
||||
struct file_end_of_file_info {
|
||||
__le64 FileSize; /* offset to end of file */
|
||||
|
@ -2409,8 +2404,7 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
|
|||
__le16 access_entry_count; /* access ACL - count of entries */
|
||||
__le16 default_entry_count; /* default ACL - count of entries */
|
||||
struct cifs_posix_ace ace_array[];
|
||||
/* followed by
|
||||
struct cifs_posix_ace default_ace_arraay[] */
|
||||
/* followed by struct cifs_posix_ace default_ace_array[] */
|
||||
} __attribute__((packed)); /* level 0x204 */
|
||||
|
||||
/* types of access control entries already defined in posix_acl.h */
|
||||
|
@ -2429,17 +2423,17 @@ struct cifs_posix_acl { /* access conrol list (ACL) */
|
|||
/* end of POSIX ACL definitions */
|
||||
|
||||
/* POSIX Open Flags */
|
||||
#define SMB_O_RDONLY 0x1
|
||||
#define SMB_O_WRONLY 0x2
|
||||
#define SMB_O_RDWR 0x4
|
||||
#define SMB_O_CREAT 0x10
|
||||
#define SMB_O_EXCL 0x20
|
||||
#define SMB_O_TRUNC 0x40
|
||||
#define SMB_O_APPEND 0x80
|
||||
#define SMB_O_SYNC 0x100
|
||||
#define SMB_O_DIRECTORY 0x200
|
||||
#define SMB_O_NOFOLLOW 0x400
|
||||
#define SMB_O_DIRECT 0x800
|
||||
#define SMB_O_RDONLY 0x1
|
||||
#define SMB_O_WRONLY 0x2
|
||||
#define SMB_O_RDWR 0x4
|
||||
#define SMB_O_CREAT 0x10
|
||||
#define SMB_O_EXCL 0x20
|
||||
#define SMB_O_TRUNC 0x40
|
||||
#define SMB_O_APPEND 0x80
|
||||
#define SMB_O_SYNC 0x100
|
||||
#define SMB_O_DIRECTORY 0x200
|
||||
#define SMB_O_NOFOLLOW 0x400
|
||||
#define SMB_O_DIRECT 0x800
|
||||
|
||||
typedef struct {
|
||||
__le32 OpenFlags; /* same as NT CreateX */
|
||||
|
@ -2716,15 +2710,13 @@ typedef struct file_xattr_info {
|
|||
__u32 xattr_value_len;
|
||||
char xattr_name[];
|
||||
/* followed by xattr_value[xattr_value_len], no pad */
|
||||
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
|
||||
level 0x205 */
|
||||
} __packed FILE_XATTR_INFO; /* extended attribute info level 0x205 */
|
||||
|
||||
/* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */
|
||||
|
||||
typedef struct file_chattr_info {
|
||||
__le64 mask; /* list of all possible attribute bits */
|
||||
__le64 mode; /* list of actual attribute bits on this inode */
|
||||
} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
|
||||
(chattr, chflags) level 0x206 */
|
||||
#endif /* POSIX */
|
||||
} __packed FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
|
||||
#endif /* POSIX */
|
||||
#endif /* _CIFSPDU_H */
|
||||
|
|
|
@ -124,7 +124,7 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
|
|||
struct kvec * /* resp vec */);
|
||||
extern int SendReceiveBlockingLock(const unsigned int xid,
|
||||
struct cifs_tcon *ptcon,
|
||||
struct smb_hdr *in_buf ,
|
||||
struct smb_hdr *in_buf,
|
||||
struct smb_hdr *out_buf,
|
||||
int *bytes_returned);
|
||||
void
|
||||
|
@ -604,8 +604,8 @@ int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
|
|||
int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
|
||||
void cifs_free_hash(struct shash_desc **sdesc);
|
||||
|
||||
extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
|
||||
unsigned int *len, unsigned int *offset);
|
||||
void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
|
||||
unsigned int *len, unsigned int *offset);
|
||||
struct cifs_chan *
|
||||
cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server);
|
||||
int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
|
||||
|
|
|
@ -2646,6 +2646,21 @@ wdata_send_pages(struct cifs_writedata *wdata, unsigned int nr_pages,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_writepage_locked(struct page *page, struct writeback_control *wbc);
|
||||
|
||||
static int cifs_write_one_page(struct page *page, struct writeback_control *wbc,
|
||||
void *data)
|
||||
{
|
||||
struct address_space *mapping = data;
|
||||
int ret;
|
||||
|
||||
ret = cifs_writepage_locked(page, wbc);
|
||||
unlock_page(page);
|
||||
mapping_set_error(mapping, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cifs_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
|
@ -2662,10 +2677,11 @@ static int cifs_writepages(struct address_space *mapping,
|
|||
|
||||
/*
|
||||
* If wsize is smaller than the page cache size, default to writing
|
||||
* one page at a time via cifs_writepage
|
||||
* one page at a time.
|
||||
*/
|
||||
if (cifs_sb->ctx->wsize < PAGE_SIZE)
|
||||
return generic_writepages(mapping, wbc);
|
||||
return write_cache_pages(mapping, wbc, cifs_write_one_page,
|
||||
mapping);
|
||||
|
||||
xid = get_xid();
|
||||
if (wbc->range_cyclic) {
|
||||
|
@ -2852,13 +2868,6 @@ retry_write:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_writepage(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
int rc = cifs_writepage_locked(page, wbc);
|
||||
unlock_page(page);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cifs_write_end(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned copied,
|
||||
struct page *page, void *fsdata)
|
||||
|
@ -5231,7 +5240,6 @@ static bool cifs_dirty_folio(struct address_space *mapping, struct folio *folio)
|
|||
const struct address_space_operations cifs_addr_ops = {
|
||||
.read_folio = cifs_read_folio,
|
||||
.readahead = cifs_readahead,
|
||||
.writepage = cifs_writepage,
|
||||
.writepages = cifs_writepages,
|
||||
.write_begin = cifs_write_begin,
|
||||
.write_end = cifs_write_end,
|
||||
|
@ -5240,10 +5248,10 @@ const struct address_space_operations cifs_addr_ops = {
|
|||
.direct_IO = cifs_direct_io,
|
||||
.invalidate_folio = cifs_invalidate_folio,
|
||||
.launder_folio = cifs_launder_folio,
|
||||
.migrate_folio = filemap_migrate_folio,
|
||||
/*
|
||||
* TODO: investigate and if useful we could add an cifs_migratePage
|
||||
* helper (under an CONFIG_MIGRATION) in the future, and also
|
||||
* investigate and add an is_dirty_writeback helper if needed
|
||||
* TODO: investigate and if useful we could add an is_dirty_writeback
|
||||
* helper if needed
|
||||
*/
|
||||
.swap_activate = cifs_swap_activate,
|
||||
.swap_deactivate = cifs_swap_deactivate,
|
||||
|
@ -5256,7 +5264,6 @@ const struct address_space_operations cifs_addr_ops = {
|
|||
*/
|
||||
const struct address_space_operations cifs_addr_ops_smallbuf = {
|
||||
.read_folio = cifs_read_folio,
|
||||
.writepage = cifs_writepage,
|
||||
.writepages = cifs_writepages,
|
||||
.write_begin = cifs_write_begin,
|
||||
.write_end = cifs_write_end,
|
||||
|
@ -5264,4 +5271,5 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
|
|||
.release_folio = cifs_release_folio,
|
||||
.invalidate_folio = cifs_invalidate_folio,
|
||||
.launder_folio = cifs_launder_folio,
|
||||
.migrate_folio = filemap_migrate_folio,
|
||||
};
|
||||
|
|
|
@ -884,16 +884,21 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
|||
ctx->nodfs = 1;
|
||||
break;
|
||||
case Opt_hard:
|
||||
if (result.negated)
|
||||
if (result.negated) {
|
||||
if (ctx->retry == 1)
|
||||
cifs_dbg(VFS, "conflicting hard vs. soft mount options\n");
|
||||
ctx->retry = 0;
|
||||
else
|
||||
} else
|
||||
ctx->retry = 1;
|
||||
break;
|
||||
case Opt_soft:
|
||||
if (result.negated)
|
||||
ctx->retry = 1;
|
||||
else
|
||||
else {
|
||||
if (ctx->retry == 1)
|
||||
cifs_dbg(VFS, "conflicting hard vs soft mount options\n");
|
||||
ctx->retry = 0;
|
||||
}
|
||||
break;
|
||||
case Opt_mapposix:
|
||||
if (result.negated)
|
||||
|
|
|
@ -632,6 +632,8 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
|
|||
|
||||
/* Fill a cifs_fattr struct with info from POSIX info struct */
|
||||
static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
|
||||
struct cifs_sid *owner,
|
||||
struct cifs_sid *group,
|
||||
struct super_block *sb, bool adjust_tz, bool symlink)
|
||||
{
|
||||
struct smb311_posix_qinfo *info = &data->posix_fi;
|
||||
|
@ -680,8 +682,8 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_ope
|
|||
}
|
||||
/* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
|
||||
|
||||
fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
|
||||
fattr->cf_gid = cifs_sb->ctx->linux_gid;
|
||||
sid_to_id(cifs_sb, owner, fattr, SIDOWNER);
|
||||
sid_to_id(cifs_sb, group, fattr, SIDGROUP);
|
||||
|
||||
cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
|
||||
fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
|
||||
|
@ -1175,6 +1177,7 @@ smb311_posix_get_inode_info(struct inode **inode,
|
|||
struct cifs_fattr fattr = {0};
|
||||
bool symlink = false;
|
||||
struct cifs_open_info_data data = {};
|
||||
struct cifs_sid owner, group;
|
||||
int rc = 0;
|
||||
int tmprc = 0;
|
||||
|
||||
|
@ -1192,7 +1195,8 @@ smb311_posix_get_inode_info(struct inode **inode,
|
|||
goto out;
|
||||
}
|
||||
|
||||
rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data, &adjust_tz,
|
||||
rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data,
|
||||
&owner, &group, &adjust_tz,
|
||||
&symlink);
|
||||
|
||||
/*
|
||||
|
@ -1201,7 +1205,8 @@ smb311_posix_get_inode_info(struct inode **inode,
|
|||
|
||||
switch (rc) {
|
||||
case 0:
|
||||
smb311_posix_info_to_fattr(&fattr, &data, sb, adjust_tz, symlink);
|
||||
smb311_posix_info_to_fattr(&fattr, &data, &owner, &group,
|
||||
sb, adjust_tz, symlink);
|
||||
break;
|
||||
case -EREMOTE:
|
||||
/* DFS link, no metadata available on this server */
|
||||
|
|
|
@ -1136,8 +1136,8 @@ cifs_free_hash(struct shash_desc **sdesc)
|
|||
* @len: Where to store the length for this page:
|
||||
* @offset: Where to store the offset for this page
|
||||
*/
|
||||
void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
|
||||
unsigned int *len, unsigned int *offset)
|
||||
void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
|
||||
unsigned int *len, unsigned int *offset)
|
||||
{
|
||||
*len = rqst->rq_pagesz;
|
||||
*offset = (page == 0) ? rqst->rq_offset : 0;
|
||||
|
|
|
@ -59,6 +59,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
__u32 desired_access, __u32 create_disposition, __u32 create_options,
|
||||
umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile,
|
||||
__u8 **extbuf, size_t *extbuflen,
|
||||
struct kvec *err_iov, int *err_buftype)
|
||||
{
|
||||
struct cop_vars *vars = NULL;
|
||||
|
@ -430,6 +431,21 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
&rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */,
|
||||
(char *)&idata->posix_fi);
|
||||
}
|
||||
if (rc == 0) {
|
||||
unsigned int length = le32_to_cpu(qi_rsp->OutputBufferLength);
|
||||
|
||||
if (length > sizeof(idata->posix_fi)) {
|
||||
char *base = (char *)rsp_iov[1].iov_base +
|
||||
le16_to_cpu(qi_rsp->OutputBufferOffset) +
|
||||
sizeof(idata->posix_fi);
|
||||
*extbuflen = length - sizeof(idata->posix_fi);
|
||||
*extbuf = kmemdup(base, *extbuflen, GFP_KERNEL);
|
||||
if (!*extbuf)
|
||||
rc = -ENOMEM;
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
}
|
||||
if (rqst[1].rq_iov)
|
||||
SMB2_query_info_free(&rqst[1]);
|
||||
if (rqst[2].rq_iov)
|
||||
|
@ -539,7 +555,7 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
|
||||
create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile,
|
||||
err_iov, err_buftype);
|
||||
NULL, NULL, err_iov, err_buftype);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
|
||||
((struct smb2_hdr *)err_iov[0].iov_base)->Command == SMB2_CREATE &&
|
||||
|
@ -555,7 +571,7 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
|
||||
FILE_OPEN, create_options, ACL_NO_MODE, data,
|
||||
SMB2_OP_QUERY_INFO, cfile, NULL, NULL);
|
||||
SMB2_OP_QUERY_INFO, cfile, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -568,13 +584,20 @@ out:
|
|||
|
||||
int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
|
||||
struct cifs_open_info_data *data,
|
||||
struct cifs_sid *owner,
|
||||
struct cifs_sid *group,
|
||||
bool *adjust_tz, bool *reparse)
|
||||
{
|
||||
int rc;
|
||||
__u32 create_options = 0;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct kvec err_iov[3] = {};
|
||||
int err_buftype[3] = {};
|
||||
__u8 *sidsbuf = NULL;
|
||||
__u8 *sidsbuf_end = NULL;
|
||||
size_t sidsbuflen = 0;
|
||||
size_t owner_len, group_len;
|
||||
|
||||
*adjust_tz = false;
|
||||
*reparse = false;
|
||||
|
@ -589,7 +612,7 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
|
||||
create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
|
||||
err_iov, err_buftype);
|
||||
&sidsbuf, &sidsbuflen, err_iov, err_buftype);
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
/* BB TODO: When support for special files added to Samba re-verify this path */
|
||||
if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
|
||||
|
@ -606,10 +629,31 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
|
||||
FILE_OPEN, create_options, ACL_NO_MODE, data,
|
||||
SMB2_OP_POSIX_QUERY_INFO, cfile, NULL, NULL);
|
||||
SMB2_OP_POSIX_QUERY_INFO, cfile,
|
||||
&sidsbuf, &sidsbuflen, NULL, NULL);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
sidsbuf_end = sidsbuf + sidsbuflen;
|
||||
|
||||
owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
|
||||
if (owner_len == -1) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(owner, sidsbuf, owner_len);
|
||||
|
||||
group_len = posix_info_sid_size(
|
||||
sidsbuf + owner_len, sidsbuf_end);
|
||||
if (group_len == -1) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(group, sidsbuf + owner_len, group_len);
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(sidsbuf);
|
||||
free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
|
||||
free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
|
||||
free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
|
||||
|
@ -624,7 +668,7 @@ smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
|
|||
return smb2_compound_op(xid, tcon, cifs_sb, name,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_CREATE,
|
||||
CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
|
||||
NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -646,7 +690,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
|
|||
tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_CREATE,
|
||||
CREATE_NOT_FILE, ACL_NO_MODE,
|
||||
&data, SMB2_OP_SET_INFO, cfile, NULL, NULL);
|
||||
&data, SMB2_OP_SET_INFO, cfile, NULL, NULL, NULL, NULL);
|
||||
if (tmprc == 0)
|
||||
cifs_i->cifsAttrs = dosattrs;
|
||||
}
|
||||
|
@ -658,7 +702,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
|||
drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
|
||||
return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
|
||||
CREATE_NOT_FILE, ACL_NO_MODE,
|
||||
NULL, SMB2_OP_RMDIR, NULL, NULL, NULL);
|
||||
NULL, SMB2_OP_RMDIR, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -667,7 +711,7 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
|
|||
{
|
||||
return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
|
||||
CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
|
||||
ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL);
|
||||
ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -686,7 +730,7 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
}
|
||||
rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
|
||||
FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
|
||||
command, cfile, NULL, NULL);
|
||||
command, cfile, NULL, NULL, NULL, NULL);
|
||||
smb2_rename_path:
|
||||
kfree(smb2_to_name);
|
||||
return rc;
|
||||
|
@ -727,7 +771,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
|
||||
return smb2_compound_op(xid, tcon, cifs_sb, full_path,
|
||||
FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
|
||||
&eof, SMB2_OP_SET_EOF, cfile, NULL, NULL);
|
||||
&eof, SMB2_OP_SET_EOF, cfile, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -754,7 +798,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
|
|||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
|
||||
FILE_WRITE_ATTRIBUTES, FILE_OPEN,
|
||||
0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL, NULL);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -4204,69 +4204,82 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
|
|||
memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
|
||||
}
|
||||
|
||||
/* We can not use the normal sg_set_buf() as we will sometimes pass a
|
||||
* stack object as buf.
|
||||
*/
|
||||
static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
|
||||
unsigned int buflen)
|
||||
static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst,
|
||||
int num_rqst, const u8 *sig, u8 **iv,
|
||||
struct aead_request **req, struct scatterlist **sgl,
|
||||
unsigned int *num_sgs)
|
||||
{
|
||||
void *addr;
|
||||
/*
|
||||
* VMAP_STACK (at least) puts stack into the vmalloc address space
|
||||
*/
|
||||
if (is_vmalloc_addr(buf))
|
||||
addr = vmalloc_to_page(buf);
|
||||
else
|
||||
addr = virt_to_page(buf);
|
||||
sg_set_page(sg, addr, buflen, offset_in_page(buf));
|
||||
}
|
||||
unsigned int req_size = sizeof(**req) + crypto_aead_reqsize(tfm);
|
||||
unsigned int iv_size = crypto_aead_ivsize(tfm);
|
||||
unsigned int len;
|
||||
u8 *p;
|
||||
|
||||
/* Assumes the first rqst has a transform header as the first iov.
|
||||
* I.e.
|
||||
* rqst[0].rq_iov[0] is transform header
|
||||
* rqst[0].rq_iov[1+] data to be encrypted/decrypted
|
||||
* rqst[1+].rq_iov[0+] data to be encrypted/decrypted
|
||||
*/
|
||||
static struct scatterlist *
|
||||
init_sg(int num_rqst, struct smb_rqst *rqst, u8 *sign)
|
||||
{
|
||||
unsigned int sg_len;
|
||||
struct scatterlist *sg;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int idx = 0;
|
||||
int skip;
|
||||
*num_sgs = cifs_get_num_sgs(rqst, num_rqst, sig);
|
||||
|
||||
sg_len = 1;
|
||||
for (i = 0; i < num_rqst; i++)
|
||||
sg_len += rqst[i].rq_nvec + rqst[i].rq_npages;
|
||||
len = iv_size;
|
||||
len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
|
||||
len = ALIGN(len, crypto_tfm_ctx_alignment());
|
||||
len += req_size;
|
||||
len = ALIGN(len, __alignof__(struct scatterlist));
|
||||
len += *num_sgs * sizeof(**sgl);
|
||||
|
||||
sg = kmalloc_array(sg_len, sizeof(struct scatterlist), GFP_KERNEL);
|
||||
if (!sg)
|
||||
p = kmalloc(len, GFP_ATOMIC);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
sg_init_table(sg, sg_len);
|
||||
*iv = (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1);
|
||||
*req = (struct aead_request *)PTR_ALIGN(*iv + iv_size,
|
||||
crypto_tfm_ctx_alignment());
|
||||
*sgl = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size,
|
||||
__alignof__(struct scatterlist));
|
||||
return p;
|
||||
}
|
||||
|
||||
static void *smb2_get_aead_req(struct crypto_aead *tfm, const struct smb_rqst *rqst,
|
||||
int num_rqst, const u8 *sig, u8 **iv,
|
||||
struct aead_request **req, struct scatterlist **sgl)
|
||||
{
|
||||
unsigned int off, len, skip;
|
||||
struct scatterlist *sg;
|
||||
unsigned int num_sgs;
|
||||
unsigned long addr;
|
||||
int i, j;
|
||||
void *p;
|
||||
|
||||
p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, sgl, &num_sgs);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
sg_init_table(*sgl, num_sgs);
|
||||
sg = *sgl;
|
||||
|
||||
/* Assumes the first rqst has a transform header as the first iov.
|
||||
* I.e.
|
||||
* rqst[0].rq_iov[0] is transform header
|
||||
* rqst[0].rq_iov[1+] data to be encrypted/decrypted
|
||||
* rqst[1+].rq_iov[0+] data to be encrypted/decrypted
|
||||
*/
|
||||
for (i = 0; i < num_rqst; i++) {
|
||||
/*
|
||||
* The first rqst has a transform header where the
|
||||
* first 20 bytes are not part of the encrypted blob.
|
||||
*/
|
||||
for (j = 0; j < rqst[i].rq_nvec; j++) {
|
||||
/*
|
||||
* The first rqst has a transform header where the
|
||||
* first 20 bytes are not part of the encrypted blob
|
||||
*/
|
||||
struct kvec *iov = &rqst[i].rq_iov[j];
|
||||
|
||||
skip = (i == 0) && (j == 0) ? 20 : 0;
|
||||
smb2_sg_set_buf(&sg[idx++],
|
||||
rqst[i].rq_iov[j].iov_base + skip,
|
||||
rqst[i].rq_iov[j].iov_len - skip);
|
||||
}
|
||||
|
||||
addr = (unsigned long)iov->iov_base + skip;
|
||||
len = iov->iov_len - skip;
|
||||
sg = cifs_sg_set_buf(sg, (void *)addr, len);
|
||||
}
|
||||
for (j = 0; j < rqst[i].rq_npages; j++) {
|
||||
unsigned int len, offset;
|
||||
|
||||
rqst_page_get_length(&rqst[i], j, &len, &offset);
|
||||
sg_set_page(&sg[idx++], rqst[i].rq_pages[j], len, offset);
|
||||
rqst_page_get_length(&rqst[i], j, &len, &off);
|
||||
sg_set_page(sg++, rqst[i].rq_pages[j], len, off);
|
||||
}
|
||||
}
|
||||
smb2_sg_set_buf(&sg[idx], sign, SMB2_SIGNATURE_SIZE);
|
||||
return sg;
|
||||
cifs_sg_set_buf(sg, sig, SMB2_SIGNATURE_SIZE);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -4314,11 +4327,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
|
|||
u8 sign[SMB2_SIGNATURE_SIZE] = {};
|
||||
u8 key[SMB3_ENC_DEC_KEY_SIZE];
|
||||
struct aead_request *req;
|
||||
char *iv;
|
||||
unsigned int iv_len;
|
||||
u8 *iv;
|
||||
DECLARE_CRYPTO_WAIT(wait);
|
||||
struct crypto_aead *tfm;
|
||||
unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
|
||||
void *creq;
|
||||
|
||||
rc = smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key);
|
||||
if (rc) {
|
||||
|
@ -4352,32 +4365,15 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
|
|||
return rc;
|
||||
}
|
||||
|
||||
req = aead_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req) {
|
||||
cifs_server_dbg(VFS, "%s: Failed to alloc aead request\n", __func__);
|
||||
creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg);
|
||||
if (unlikely(!creq))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!enc) {
|
||||
memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
|
||||
crypt_len += SMB2_SIGNATURE_SIZE;
|
||||
}
|
||||
|
||||
sg = init_sg(num_rqst, rqst, sign);
|
||||
if (!sg) {
|
||||
cifs_server_dbg(VFS, "%s: Failed to init sg\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto free_req;
|
||||
}
|
||||
|
||||
iv_len = crypto_aead_ivsize(tfm);
|
||||
iv = kzalloc(iv_len, GFP_KERNEL);
|
||||
if (!iv) {
|
||||
cifs_server_dbg(VFS, "%s: Failed to alloc iv\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto free_sg;
|
||||
}
|
||||
|
||||
if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
|
||||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
|
||||
memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
|
||||
|
@ -4386,6 +4382,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
|
|||
memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
|
||||
}
|
||||
|
||||
aead_request_set_tfm(req, tfm);
|
||||
aead_request_set_crypt(req, sg, sg, crypt_len, iv);
|
||||
aead_request_set_ad(req, assoc_data_len);
|
||||
|
||||
|
@ -4398,11 +4395,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
|
|||
if (!rc && enc)
|
||||
memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
|
||||
|
||||
kfree_sensitive(iv);
|
||||
free_sg:
|
||||
kfree_sensitive(sg);
|
||||
free_req:
|
||||
kfree_sensitive(req);
|
||||
kfree_sensitive(creq);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -4445,21 +4438,27 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
|
|||
int rc = -ENOMEM;
|
||||
|
||||
for (i = 1; i < num_rqst; i++) {
|
||||
npages = old_rq[i - 1].rq_npages;
|
||||
struct smb_rqst *old = &old_rq[i - 1];
|
||||
struct smb_rqst *new = &new_rq[i];
|
||||
|
||||
orig_len += smb_rqst_len(server, old);
|
||||
new->rq_iov = old->rq_iov;
|
||||
new->rq_nvec = old->rq_nvec;
|
||||
|
||||
npages = old->rq_npages;
|
||||
if (!npages)
|
||||
continue;
|
||||
|
||||
pages = kmalloc_array(npages, sizeof(struct page *),
|
||||
GFP_KERNEL);
|
||||
if (!pages)
|
||||
goto err_free;
|
||||
|
||||
new_rq[i].rq_pages = pages;
|
||||
new_rq[i].rq_npages = npages;
|
||||
new_rq[i].rq_offset = old_rq[i - 1].rq_offset;
|
||||
new_rq[i].rq_pagesz = old_rq[i - 1].rq_pagesz;
|
||||
new_rq[i].rq_tailsz = old_rq[i - 1].rq_tailsz;
|
||||
new_rq[i].rq_iov = old_rq[i - 1].rq_iov;
|
||||
new_rq[i].rq_nvec = old_rq[i - 1].rq_nvec;
|
||||
|
||||
orig_len += smb_rqst_len(server, &old_rq[i - 1]);
|
||||
new->rq_pages = pages;
|
||||
new->rq_npages = npages;
|
||||
new->rq_offset = old->rq_offset;
|
||||
new->rq_pagesz = old->rq_pagesz;
|
||||
new->rq_tailsz = old->rq_tailsz;
|
||||
|
||||
for (j = 0; j < npages; j++) {
|
||||
pages[j] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
|
||||
|
@ -4472,14 +4471,14 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
|
|||
char *dst, *src;
|
||||
unsigned int offset, len;
|
||||
|
||||
rqst_page_get_length(&new_rq[i], j, &len, &offset);
|
||||
rqst_page_get_length(new, j, &len, &offset);
|
||||
|
||||
dst = (char *) kmap(new_rq[i].rq_pages[j]) + offset;
|
||||
src = (char *) kmap(old_rq[i - 1].rq_pages[j]) + offset;
|
||||
dst = kmap_local_page(new->rq_pages[j]) + offset;
|
||||
src = kmap_local_page(old->rq_pages[j]) + offset;
|
||||
|
||||
memcpy(dst, src, len);
|
||||
kunmap(new_rq[i].rq_pages[j]);
|
||||
kunmap(old_rq[i - 1].rq_pages[j]);
|
||||
kunmap(new->rq_pages[j]);
|
||||
kunmap(old->rq_pages[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -277,7 +277,10 @@ extern int smb2_query_info_compound(const unsigned int xid,
|
|||
/* query path info from the server using SMB311 POSIX extensions*/
|
||||
int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||
struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
|
||||
struct cifs_open_info_data *data,
|
||||
struct cifs_sid *owner,
|
||||
struct cifs_sid *group,
|
||||
bool *adjust_tz, bool *reparse);
|
||||
int posix_info_parse(const void *beg, const void *end,
|
||||
struct smb2_posix_info_parsed *out);
|
||||
int posix_info_sid_size(const void *beg, const void *end);
|
||||
|
|
Loading…
Reference in New Issue