mirror of
https://github.com/torvalds/linux.git
synced 2026-10-11 12:58:02 +02:00
ksmbd: support access-based directory enumeration
SMB shares can advertise access-based directory enumeration. ksmbd does not currently provide a share option or filter inaccessible directory entries. Add a hide-unreadable share flag and advertise SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM when it is enabled. During QUERY_DIRECTORY, omit entries unless the connected user has FILE_READ_DATA, FILE_READ_EA, and FILE_READ_ATTRIBUTES access according to the Windows ACL. Keep the existing implicit access allowances for normal CREATE permission checks while using strict access-mask matching for directory enumeration. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
cc2f133e80
commit
e5f42cb757
|
|
@ -377,6 +377,7 @@ enum KSMBD_TREE_CONN_STATUS {
|
|||
#define KSMBD_SHARE_FLAG_UPDATE BIT(14)
|
||||
#define KSMBD_SHARE_FLAG_CROSSMNT BIT(15)
|
||||
#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY BIT(16)
|
||||
#define KSMBD_SHARE_FLAG_HIDE_UNREADABLE BIT(17)
|
||||
|
||||
/*
|
||||
* Tree connect request flags.
|
||||
|
|
|
|||
|
|
@ -2346,6 +2346,10 @@ int smb2_tree_connect(struct ksmbd_work *work)
|
|||
if (conn->dialect == SMB311_PROT_ID &&
|
||||
conn->compress_algorithm != SMB3_COMPRESS_NONE)
|
||||
rsp->ShareFlags |= cpu_to_le32(SMB2_SHAREFLAG_COMPRESS_DATA);
|
||||
if (share && test_share_config_flag(share,
|
||||
KSMBD_SHARE_FLAG_HIDE_UNREADABLE))
|
||||
rsp->ShareFlags |=
|
||||
cpu_to_le32(SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM);
|
||||
|
||||
rc = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_tree_connect_rsp));
|
||||
if (rc)
|
||||
|
|
@ -3620,7 +3624,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||
if (file_present && !(req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) {
|
||||
rc = smb_check_perm_dacl(conn, &path, &daccess,
|
||||
req->DesiredAccess,
|
||||
sess->user->uid);
|
||||
sess->user->uid, false);
|
||||
if (rc)
|
||||
goto err_out;
|
||||
}
|
||||
|
|
@ -4595,6 +4599,7 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
|
|||
|
||||
for (i = 0; i < priv->d_info->num_entry; i++) {
|
||||
struct dentry *dent;
|
||||
struct path path;
|
||||
|
||||
if (dentry_name(priv->d_info, priv->info_level))
|
||||
return -EINVAL;
|
||||
|
|
@ -4617,6 +4622,23 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (test_share_config_flag(priv->work->tcon->share_conf,
|
||||
KSMBD_SHARE_FLAG_HIDE_UNREADABLE)) {
|
||||
__le32 daccess = FILE_READ_DATA_LE | FILE_READ_EA_LE |
|
||||
FILE_READ_ATTRIBUTES_LE;
|
||||
|
||||
path.mnt = priv->dir_fp->filp->f_path.mnt;
|
||||
path.dentry = dent;
|
||||
rc = smb_check_perm_dacl(priv->work->conn, &path,
|
||||
&daccess, daccess,
|
||||
priv->work->sess->user->uid,
|
||||
true);
|
||||
if (rc) {
|
||||
dput(dent);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ksmbd_kstat.kstat = &kstat;
|
||||
if (priv->info_level != FILE_NAMES_INFORMATION) {
|
||||
rc = ksmbd_vfs_fill_dentry_attrs(priv->work,
|
||||
|
|
|
|||
|
|
@ -1432,7 +1432,8 @@ bool smb_inherit_flags(int flags, bool is_dir)
|
|||
}
|
||||
|
||||
int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
|
||||
__le32 *pdaccess, __le32 raw_daccess, int uid)
|
||||
__le32 *pdaccess, __le32 raw_daccess, int uid,
|
||||
bool strict)
|
||||
{
|
||||
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
|
||||
struct smb_ntsd *pntsd = NULL;
|
||||
|
|
@ -1617,8 +1618,14 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
|
|||
}
|
||||
|
||||
check_access_bits:
|
||||
if (granted &
|
||||
~(access_bits | FILE_READ_ATTRIBUTES | READ_CONTROL | WRITE_DAC | DELETE)) {
|
||||
if (strict) {
|
||||
access_bits &= granted;
|
||||
} else {
|
||||
access_bits |= FILE_READ_ATTRIBUTES | READ_CONTROL |
|
||||
WRITE_DAC | DELETE;
|
||||
}
|
||||
|
||||
if (granted & ~access_bits) {
|
||||
ksmbd_debug(SMB, "Access denied with winACL, granted : %x, access_req : %x\n",
|
||||
granted, le32_to_cpu(ace->access_req));
|
||||
rc = -EACCES;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ bool smb_inherit_flags(int flags, bool is_dir);
|
|||
int smb_inherit_dacl(struct ksmbd_conn *conn, const struct path *path,
|
||||
unsigned int uid, unsigned int gid);
|
||||
int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
|
||||
__le32 *pdaccess, __le32 raw_daccess, int uid);
|
||||
__le32 *pdaccess, __le32 raw_daccess, int uid,
|
||||
bool strict);
|
||||
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
|
||||
const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
|
||||
bool type_check, bool get_write);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user