Skip to content

Commit

Permalink
Merge tag 'v6.14-rc-smb3-client-fixes-part2' of git://git.samba.org/s…
Browse files Browse the repository at this point in the history
…french/cifs-2.6

Pull more smb client updates from Steve French:

   - various updates for special file handling: symlink handling,
     support for creating sockets, cleanups, new mount options (e.g. to
     allow disabling using reparse points for them, and to allow
     overriding the way symlinks are saved), and fixes to error paths

   - fix for kerberos mounts (allow IAKerb)

   - SMB1 fix for stat and for setting SACL (auditing)

   - fix an incorrect error code mapping

   - cleanups"

* tag 'v6.14-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6: (21 commits)
  cifs: Fix parsing native symlinks directory/file type
  cifs: update internal version number
  cifs: Add support for creating WSL-style symlinks
  smb3: add support for IAKerb
  cifs: Fix struct FILE_ALL_INFO
  cifs: Add support for creating NFS-style symlinks
  cifs: Add support for creating native Windows sockets
  cifs: Add mount option -o reparse=none
  cifs: Add mount option -o symlink= for choosing symlink create type
  cifs: Fix creating and resolving absolute NT-style symlinks
  cifs: Simplify reparse point check in cifs_query_path_info() function
  cifs: Remove symlink member from cifs_open_info_data union
  cifs: Update description about ACL permissions
  cifs: Rename struct reparse_posix_data to reparse_nfs_data_buffer and move to common/smb2pdu.h
  cifs: Remove struct reparse_posix_data from struct cifs_open_info_data
  cifs: Remove unicode parameter from parse_reparse_point() function
  cifs: Fix getting and setting SACLs over SMB1
  cifs: Remove intermediate object of failed create SFU call
  cifs: Validate EAs for WSL reparse points
  cifs: Change translation of STATUS_PRIVILEGE_NOT_HELD to -EPERM
  ...
  • Loading branch information
Linus Torvalds committed Feb 1, 2025
2 parents 8c198ff + a49da4e commit cabb468
Show file tree
Hide file tree
Showing 28 changed files with 884 additions and 192 deletions.
2 changes: 2 additions & 0 deletions fs/smb/client/asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ int cifs_neg_token_init_mech_type(void *context, size_t hdrlen,
server->sec_kerberos = true;
else if (oid == OID_ntlmssp)
server->sec_ntlmssp = true;
else if (oid == OID_IAKerb)
server->sec_iakerb = true;
else {
char buf[50];

Expand Down
4 changes: 3 additions & 1 deletion fs/smb/client/cifs_spnego.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,13 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,

dp = description + strlen(description);

/* for now, only sec=krb5 and sec=mskrb5 are valid */
/* for now, only sec=krb5 and sec=mskrb5 and iakerb are valid */
if (server->sec_kerberos)
sprintf(dp, ";sec=krb5");
else if (server->sec_mskerberos)
sprintf(dp, ";sec=mskrb5");
else if (server->sec_iakerb)
sprintf(dp, ";sec=iakerb");
else {
cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
sprintf(dp, ";sec=krb5");
Expand Down
25 changes: 15 additions & 10 deletions fs/smb/client/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,7 @@ static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd,
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
const struct cifs_fid *cifsfid, u32 *pacllen,
u32 __maybe_unused unused)
u32 info)
{
struct smb_ntsd *pntsd = NULL;
unsigned int xid;
Expand All @@ -1407,7 +1407,7 @@ struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,

xid = get_xid();
rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
pacllen);
pacllen, info);
free_xid(xid);

cifs_put_tlink(tlink);
Expand All @@ -1419,7 +1419,7 @@ struct smb_ntsd *get_cifs_acl_by_fid(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, u32 info)
{
struct smb_ntsd *pntsd = NULL;
int oplock = 0;
Expand All @@ -1446,9 +1446,12 @@ static struct smb_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
.fid = &fid,
};

if (info & SACL_SECINFO)
oparms.desired_access |= SYSTEM_SECURITY;

rc = CIFS_open(xid, &oparms, &oplock, NULL);
if (!rc) {
rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen, info);
CIFSSMBClose(xid, tcon, fid.netfid);
}

Expand All @@ -1472,7 +1475,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
if (inode)
open_file = find_readable_file(CIFS_I(inode), true);
if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen);
return get_cifs_acl_by_path(cifs_sb, path, pacllen, info);

pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen, info);
cifsFileInfo_put(open_file);
Expand All @@ -1485,7 +1488,7 @@ int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen,
{
int oplock = 0;
unsigned int xid;
int rc, access_flags;
int rc, access_flags = 0;
struct cifs_tcon *tcon;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Expand All @@ -1498,10 +1501,12 @@ int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen,
tcon = tlink_tcon(tlink);
xid = get_xid();

if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
access_flags = WRITE_OWNER;
else
access_flags = WRITE_DAC;
if (aclflag & CIFS_ACL_OWNER || aclflag & CIFS_ACL_GROUP)
access_flags |= WRITE_OWNER;
if (aclflag & CIFS_ACL_SACL)
access_flags |= SYSTEM_SECURITY;
if (aclflag & CIFS_ACL_DACL)
access_flags |= WRITE_DAC;

oparms = (struct cifs_open_parms) {
.tcon = tcon,
Expand Down
6 changes: 6 additions & 0 deletions fs/smb/client/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,12 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
cifs_sb->ctx->backupgid));
seq_show_option(s, "reparse",
cifs_reparse_type_str(cifs_sb->ctx->reparse_type));
if (cifs_sb->ctx->nonativesocket)
seq_puts(s, ",nonativesocket");
else
seq_puts(s, ",nativesocket");
seq_show_option(s, "symlink",
cifs_symlink_type_str(get_cifs_symlink_type(cifs_sb)));

seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize);
seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize);
Expand Down
4 changes: 2 additions & 2 deletions fs/smb/client/cifsfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

/* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 52
#define CIFS_VERSION "2.52"
#define SMB3_PRODUCT_BUILD 53
#define CIFS_VERSION "2.53"
#endif /* _CIFSFS_H */
62 changes: 49 additions & 13 deletions fs/smb/client/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ enum securityEnum {
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
Kerberos, /* Kerberos via SPNEGO */
IAKerb, /* Kerberos proxy */
};

enum upcall_target_enum {
Expand All @@ -160,6 +161,7 @@ enum upcall_target_enum {
};

enum cifs_reparse_type {
CIFS_REPARSE_TYPE_NONE,
CIFS_REPARSE_TYPE_NFS,
CIFS_REPARSE_TYPE_WSL,
CIFS_REPARSE_TYPE_DEFAULT = CIFS_REPARSE_TYPE_NFS,
Expand All @@ -168,6 +170,8 @@ enum cifs_reparse_type {
static inline const char *cifs_reparse_type_str(enum cifs_reparse_type type)
{
switch (type) {
case CIFS_REPARSE_TYPE_NONE:
return "none";
case CIFS_REPARSE_TYPE_NFS:
return "nfs";
case CIFS_REPARSE_TYPE_WSL:
Expand All @@ -177,6 +181,39 @@ static inline const char *cifs_reparse_type_str(enum cifs_reparse_type type)
}
}

enum cifs_symlink_type {
CIFS_SYMLINK_TYPE_DEFAULT,
CIFS_SYMLINK_TYPE_NONE,
CIFS_SYMLINK_TYPE_NATIVE,
CIFS_SYMLINK_TYPE_UNIX,
CIFS_SYMLINK_TYPE_MFSYMLINKS,
CIFS_SYMLINK_TYPE_SFU,
CIFS_SYMLINK_TYPE_NFS,
CIFS_SYMLINK_TYPE_WSL,
};

static inline const char *cifs_symlink_type_str(enum cifs_symlink_type type)
{
switch (type) {
case CIFS_SYMLINK_TYPE_NONE:
return "none";
case CIFS_SYMLINK_TYPE_NATIVE:
return "native";
case CIFS_SYMLINK_TYPE_UNIX:
return "unix";
case CIFS_SYMLINK_TYPE_MFSYMLINKS:
return "mfsymlinks";
case CIFS_SYMLINK_TYPE_SFU:
return "sfu";
case CIFS_SYMLINK_TYPE_NFS:
return "nfs";
case CIFS_SYMLINK_TYPE_WSL:
return "wsl";
default:
return "unknown";
}
}

struct session_key {
unsigned int len;
char *response;
Expand Down Expand Up @@ -215,21 +252,15 @@ struct cifs_cred {

struct cifs_open_info_data {
bool adjust_tz;
union {
bool reparse_point;
bool symlink;
};
bool reparse_point;
struct {
/* ioctl response buffer */
struct {
int buftype;
struct kvec iov;
} io;
__u32 tag;
union {
struct reparse_data_buffer *buf;
struct reparse_posix_data *posix;
};
struct reparse_data_buffer *buf;
} reparse;
struct {
__u8 eas[SMB2_WSL_MAX_QUERY_EA_RESP_SIZE];
Expand Down Expand Up @@ -751,6 +782,7 @@ struct TCP_Server_Info {
bool sec_kerberosu2u; /* supports U2U Kerberos */
bool sec_kerberos; /* supports plain Kerberos */
bool sec_mskerberos; /* supports legacy MS Kerberos */
bool sec_iakerb; /* supports pass-through auth for Kerberos (krb5 proxy) */
bool large_buf; /* is current buffer large? */
/* use SMBD connection instead of socket */
bool rdma;
Expand Down Expand Up @@ -2118,6 +2150,8 @@ static inline char *get_security_type_str(enum securityEnum sectype)
return "Kerberos";
case NTLMv2:
return "NTLMv2";
case IAKerb:
return "IAKerb";
default:
return "Unknown";
}
Expand Down Expand Up @@ -2173,11 +2207,13 @@ static inline size_t ntlmssp_workstation_name_size(const struct cifs_ses *ses)

static inline void move_cifs_info_to_smb2(struct smb2_file_all_info *dst, const FILE_ALL_INFO *src)
{
memcpy(dst, src, (size_t)((u8 *)&src->AccessFlags - (u8 *)src));
dst->AccessFlags = src->AccessFlags;
dst->CurrentByteOffset = src->CurrentByteOffset;
dst->Mode = src->Mode;
dst->AlignmentRequirement = src->AlignmentRequirement;
memcpy(dst, src, (size_t)((u8 *)&src->EASize - (u8 *)src));
dst->IndexNumber = 0;
dst->EASize = src->EASize;
dst->AccessFlags = 0;
dst->CurrentByteOffset = 0;
dst->Mode = 0;
dst->AlignmentRequirement = 0;
dst->FileNameLength = src->FileNameLength;
}

Expand Down
102 changes: 61 additions & 41 deletions fs/smb/client/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,42 +190,82 @@
*/

#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
/* or directory child entries can */
/* be listed together with the */
/* associated child attributes */
/* (so the FILE_READ_ATTRIBUTES on */
/* the child entry is not needed) */
#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
/* or new file can be created in */
/* the directory */
#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
/* (for non-local files over SMB it */
/* is same as FILE_WRITE_DATA) */
/* or new subdirectory can be */
/* created in the directory */
#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
/* with the file can be read */
#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
/* with the file can be written */
#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
/* the file using system paging I/O */
#define FILE_DELETE_CHILD 0x00000040
/* for executing the file / script */
/* or right to traverse directory */
/* (but by default all users have */
/* directory bypass traverse */
/* privilege and do not need this */
/* permission on directories at all)*/
#define FILE_DELETE_CHILD 0x00000040 /* Child entry can be deleted from */
/* the directory (so the DELETE on */
/* the child entry is not needed) */
#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
/* file can be read */
/* file or directory can be read */
#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
/* file can be written */
#define DELETE 0x00010000 /* The file can be deleted */
#define READ_CONTROL 0x00020000 /* The access control list and */
/* ownership associated with the */
/* file can be read */
#define WRITE_DAC 0x00040000 /* The access control list and */
/* ownership associated with the */
/* file can be written. */
/* file or directory can be written */
#define DELETE 0x00010000 /* The file or dir can be deleted */
#define READ_CONTROL 0x00020000 /* The discretionary access control */
/* list and ownership associated */
/* with the file or dir can be read */
#define WRITE_DAC 0x00040000 /* The discretionary access control */
/* list associated with the file or */
/* directory can be written */
#define WRITE_OWNER 0x00080000 /* Ownership information associated */
/* with the file can be written */
/* with the file/dir can be written */
#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
/* synchronize with the completion */
/* of an input/output request */
#define SYSTEM_SECURITY 0x01000000 /* The system access control list */
/* can be read and changed */
#define GENERIC_ALL 0x10000000
#define GENERIC_EXECUTE 0x20000000
#define GENERIC_WRITE 0x40000000
#define GENERIC_READ 0x80000000
/* In summary - Relevant file */
/* access flags from CIFS are */
/* file_read_data, file_write_data */
/* file_execute, file_read_attributes*/
/* write_dac, and delete. */
/* associated with the file or */
/* directory can be read or written */
/* (cannot be in DACL, can in SACL) */
#define MAXIMUM_ALLOWED 0x02000000 /* Maximal subset of GENERIC_ALL */
/* permissions which can be granted */
/* (cannot be in DACL nor SACL) */
#define GENERIC_ALL 0x10000000 /* Same as: GENERIC_EXECUTE | */
/* GENERIC_WRITE | */
/* GENERIC_READ | */
/* FILE_DELETE_CHILD | */
/* DELETE | */
/* WRITE_DAC | */
/* WRITE_OWNER */
/* So GENERIC_ALL contains all bits */
/* mentioned above except these two */
/* SYSTEM_SECURITY MAXIMUM_ALLOWED */
#define GENERIC_EXECUTE 0x20000000 /* Same as: FILE_EXECUTE | */
/* FILE_READ_ATTRIBUTES | */
/* READ_CONTROL | */
/* SYNCHRONIZE */
#define GENERIC_WRITE 0x40000000 /* Same as: FILE_WRITE_DATA | */
/* FILE_APPEND_DATA | */
/* FILE_WRITE_EA | */
/* FILE_WRITE_ATTRIBUTES | */
/* READ_CONTROL | */
/* SYNCHRONIZE */
#define GENERIC_READ 0x80000000 /* Same as: FILE_READ_DATA | */
/* FILE_READ_EA | */
/* FILE_READ_ATTRIBUTES | */
/* READ_CONTROL | */
/* SYNCHRONIZE */

#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
Expand Down Expand Up @@ -1484,20 +1524,6 @@ struct file_notify_information {
__u8 FileName[];
} __attribute__((packed));

/* For IO_REPARSE_TAG_NFS */
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
#define NFS_SPECFILE_CHR 0x0000000000524843
#define NFS_SPECFILE_BLK 0x00000000004B4C42
#define NFS_SPECFILE_FIFO 0x000000004F464946
#define NFS_SPECFILE_SOCK 0x000000004B434F53
struct reparse_posix_data {
__le32 ReparseTag;
__le16 ReparseDataLength;
__u16 Reserved;
__le64 InodeType; /* LNK, FIFO, CHR etc. */
__u8 DataBuffer[];
} __attribute__((packed));

struct cifs_quota_data {
__u32 rsrvd1; /* 0 */
__u32 sid_size;
Expand Down Expand Up @@ -2264,13 +2290,7 @@ typedef struct { /* data block encoding of response to level 263 QPathInfo */
__u8 DeletePending;
__u8 Directory;
__u16 Pad2;
__le64 IndexNumber;
__le32 EASize;
__le32 AccessFlags;
__u64 IndexNumber1;
__le64 CurrentByteOffset;
__le32 Mode;
__le32 AlignmentRequirement;
__le32 FileNameLength;
union {
char __pad;
Expand Down
Loading

0 comments on commit cabb468

Please sign in to comment.