Commit 3867369e authored by Namjae Jeon's avatar Namjae Jeon

ksmbd: change data type of volatile/persistent id to u64

This patch change data type of volatile/persistent id to u64 to make
issue from idr_find and idr_remove(). !HAS_FILE_ID check will protect
integer overflow issue from idr_find and idr_remove().
Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent a9071e3c
...@@ -43,9 +43,9 @@ struct ksmbd_work { ...@@ -43,9 +43,9 @@ struct ksmbd_work {
* Current Local FID assigned compound response if SMB2 CREATE * Current Local FID assigned compound response if SMB2 CREATE
* command is present in compound request * command is present in compound request
*/ */
unsigned int compound_fid; u64 compound_fid;
unsigned int compound_pfid; u64 compound_pfid;
unsigned int compound_sid; u64 compound_sid;
const struct cred *saved_cred; const struct cred *saved_cred;
......
...@@ -2809,7 +2809,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2809,7 +2809,7 @@ int smb2_open(struct ksmbd_work *work)
/* Get Persistent-ID */ /* Get Persistent-ID */
ksmbd_open_durable_fd(fp); ksmbd_open_durable_fd(fp);
if (!HAS_FILE_ID(fp->persistent_id)) { if (!has_file_id(fp->persistent_id)) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_out; goto err_out;
} }
...@@ -4577,15 +4577,15 @@ static int smb2_get_info_file(struct ksmbd_work *work, ...@@ -4577,15 +4577,15 @@ static int smb2_get_info_file(struct ksmbd_work *work,
} }
if (work->next_smb2_rcv_hdr_off) { if (work->next_smb2_rcv_hdr_off) {
if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) { if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
ksmbd_debug(SMB, "Compound request set FID = %u\n", ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid); work->compound_fid);
id = work->compound_fid; id = work->compound_fid;
pid = work->compound_pfid; pid = work->compound_pfid;
} }
} }
if (!HAS_FILE_ID(id)) { if (!has_file_id(id)) {
id = le64_to_cpu(req->VolatileFileId); id = le64_to_cpu(req->VolatileFileId);
pid = le64_to_cpu(req->PersistentFileId); pid = le64_to_cpu(req->PersistentFileId);
} }
...@@ -4949,15 +4949,15 @@ static int smb2_get_info_sec(struct ksmbd_work *work, ...@@ -4949,15 +4949,15 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
} }
if (work->next_smb2_rcv_hdr_off) { if (work->next_smb2_rcv_hdr_off) {
if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) { if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
ksmbd_debug(SMB, "Compound request set FID = %u\n", ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid); work->compound_fid);
id = work->compound_fid; id = work->compound_fid;
pid = work->compound_pfid; pid = work->compound_pfid;
} }
} }
if (!HAS_FILE_ID(id)) { if (!has_file_id(id)) {
id = le64_to_cpu(req->VolatileFileId); id = le64_to_cpu(req->VolatileFileId);
pid = le64_to_cpu(req->PersistentFileId); pid = le64_to_cpu(req->PersistentFileId);
} }
...@@ -5083,7 +5083,7 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work) ...@@ -5083,7 +5083,7 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work)
*/ */
int smb2_close(struct ksmbd_work *work) int smb2_close(struct ksmbd_work *work)
{ {
unsigned int volatile_id = KSMBD_NO_FID; u64 volatile_id = KSMBD_NO_FID;
u64 sess_id; u64 sess_id;
struct smb2_close_req *req; struct smb2_close_req *req;
struct smb2_close_rsp *rsp; struct smb2_close_rsp *rsp;
...@@ -5119,15 +5119,16 @@ int smb2_close(struct ksmbd_work *work) ...@@ -5119,15 +5119,16 @@ int smb2_close(struct ksmbd_work *work)
} }
if (work->next_smb2_rcv_hdr_off && if (work->next_smb2_rcv_hdr_off &&
!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) { !has_file_id(le64_to_cpu(req->VolatileFileId))) {
if (!HAS_FILE_ID(work->compound_fid)) { if (!has_file_id(work->compound_fid)) {
/* file already closed, return FILE_CLOSED */ /* file already closed, return FILE_CLOSED */
ksmbd_debug(SMB, "file already closed\n"); ksmbd_debug(SMB, "file already closed\n");
rsp->hdr.Status = STATUS_FILE_CLOSED; rsp->hdr.Status = STATUS_FILE_CLOSED;
err = -EBADF; err = -EBADF;
goto out; goto out;
} else { } else {
ksmbd_debug(SMB, "Compound request set FID = %u:%u\n", ksmbd_debug(SMB,
"Compound request set FID = %llu:%llu\n",
work->compound_fid, work->compound_fid,
work->compound_pfid); work->compound_pfid);
volatile_id = work->compound_fid; volatile_id = work->compound_fid;
...@@ -5139,7 +5140,7 @@ int smb2_close(struct ksmbd_work *work) ...@@ -5139,7 +5140,7 @@ int smb2_close(struct ksmbd_work *work)
} else { } else {
volatile_id = le64_to_cpu(req->VolatileFileId); volatile_id = le64_to_cpu(req->VolatileFileId);
} }
ksmbd_debug(SMB, "volatile_id = %u\n", volatile_id); ksmbd_debug(SMB, "volatile_id = %llu\n", volatile_id);
rsp->StructureSize = cpu_to_le16(60); rsp->StructureSize = cpu_to_le16(60);
rsp->Reserved = 0; rsp->Reserved = 0;
...@@ -5789,8 +5790,8 @@ int smb2_set_info(struct ksmbd_work *work) ...@@ -5789,8 +5790,8 @@ int smb2_set_info(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off) { if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work); req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work); rsp = ksmbd_resp_buf_next(work);
if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) { if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
ksmbd_debug(SMB, "Compound request set FID = %u\n", ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid); work->compound_fid);
id = work->compound_fid; id = work->compound_fid;
pid = work->compound_pfid; pid = work->compound_pfid;
...@@ -5800,7 +5801,7 @@ int smb2_set_info(struct ksmbd_work *work) ...@@ -5800,7 +5801,7 @@ int smb2_set_info(struct ksmbd_work *work)
rsp = work->response_buf; rsp = work->response_buf;
} }
if (!HAS_FILE_ID(id)) { if (!has_file_id(id)) {
id = le64_to_cpu(req->VolatileFileId); id = le64_to_cpu(req->VolatileFileId);
pid = le64_to_cpu(req->PersistentFileId); pid = le64_to_cpu(req->PersistentFileId);
} }
...@@ -7287,8 +7288,8 @@ int smb2_ioctl(struct ksmbd_work *work) ...@@ -7287,8 +7288,8 @@ int smb2_ioctl(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off) { if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work); req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work); rsp = ksmbd_resp_buf_next(work);
if (!HAS_FILE_ID(le64_to_cpu(req->VolatileFileId))) { if (!has_file_id(le64_to_cpu(req->VolatileFileId))) {
ksmbd_debug(SMB, "Compound request set FID = %u\n", ksmbd_debug(SMB, "Compound request set FID = %llu\n",
work->compound_fid); work->compound_fid);
id = work->compound_fid; id = work->compound_fid;
} }
...@@ -7297,7 +7298,7 @@ int smb2_ioctl(struct ksmbd_work *work) ...@@ -7297,7 +7298,7 @@ int smb2_ioctl(struct ksmbd_work *work)
rsp = work->response_buf; rsp = work->response_buf;
} }
if (!HAS_FILE_ID(id)) if (!has_file_id(id))
id = le64_to_cpu(req->VolatileFileId); id = le64_to_cpu(req->VolatileFileId);
if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) { if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
......
...@@ -277,7 +277,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp) ...@@ -277,7 +277,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp) static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp)
{ {
if (!HAS_FILE_ID(fp->persistent_id)) if (!has_file_id(fp->persistent_id))
return; return;
write_lock(&global_ft.lock); write_lock(&global_ft.lock);
...@@ -287,7 +287,7 @@ static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp) ...@@ -287,7 +287,7 @@ static void __ksmbd_remove_durable_fd(struct ksmbd_file *fp)
static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp) static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
{ {
if (!HAS_FILE_ID(fp->volatile_id)) if (!has_file_id(fp->volatile_id))
return; return;
write_lock(&fp->f_ci->m_lock); write_lock(&fp->f_ci->m_lock);
...@@ -327,10 +327,13 @@ static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp) ...@@ -327,10 +327,13 @@ static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp)
} }
static struct ksmbd_file *__ksmbd_lookup_fd(struct ksmbd_file_table *ft, static struct ksmbd_file *__ksmbd_lookup_fd(struct ksmbd_file_table *ft,
unsigned int id) u64 id)
{ {
struct ksmbd_file *fp; struct ksmbd_file *fp;
if (!has_file_id(id))
return NULL;
read_lock(&ft->lock); read_lock(&ft->lock);
fp = idr_find(ft->idr, id); fp = idr_find(ft->idr, id);
if (fp) if (fp)
...@@ -359,12 +362,12 @@ static void set_close_state_blocked_works(struct ksmbd_file *fp) ...@@ -359,12 +362,12 @@ static void set_close_state_blocked_works(struct ksmbd_file *fp)
spin_unlock(&fp->f_lock); spin_unlock(&fp->f_lock);
} }
int ksmbd_close_fd(struct ksmbd_work *work, unsigned int id) int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
{ {
struct ksmbd_file *fp; struct ksmbd_file *fp;
struct ksmbd_file_table *ft; struct ksmbd_file_table *ft;
if (!HAS_FILE_ID(id)) if (!has_file_id(id))
return 0; return 0;
ft = &work->sess->file_table; ft = &work->sess->file_table;
...@@ -404,12 +407,12 @@ static bool __sanity_check(struct ksmbd_tree_connect *tcon, struct ksmbd_file *f ...@@ -404,12 +407,12 @@ static bool __sanity_check(struct ksmbd_tree_connect *tcon, struct ksmbd_file *f
return true; return true;
} }
struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, unsigned int id) struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id)
{ {
return __ksmbd_lookup_fd(&work->sess->file_table, id); return __ksmbd_lookup_fd(&work->sess->file_table, id);
} }
struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, unsigned int id) struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id)
{ {
struct ksmbd_file *fp = __ksmbd_lookup_fd(&work->sess->file_table, id); struct ksmbd_file *fp = __ksmbd_lookup_fd(&work->sess->file_table, id);
...@@ -420,19 +423,16 @@ struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, unsigned int id ...@@ -420,19 +423,16 @@ struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, unsigned int id
return NULL; return NULL;
} }
struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, unsigned int id, struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
unsigned int pid) u64 pid)
{ {
struct ksmbd_file *fp; struct ksmbd_file *fp;
if (!HAS_FILE_ID(id)) { if (!has_file_id(id)) {
id = work->compound_fid; id = work->compound_fid;
pid = work->compound_pfid; pid = work->compound_pfid;
} }
if (!HAS_FILE_ID(id))
return NULL;
fp = __ksmbd_lookup_fd(&work->sess->file_table, id); fp = __ksmbd_lookup_fd(&work->sess->file_table, id);
if (!__sanity_check(work->tcon, fp)) { if (!__sanity_check(work->tcon, fp)) {
ksmbd_fd_put(work, fp); ksmbd_fd_put(work, fp);
...@@ -494,7 +494,7 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode) ...@@ -494,7 +494,7 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode)
#define OPEN_ID_TYPE_VOLATILE_ID (0) #define OPEN_ID_TYPE_VOLATILE_ID (0)
#define OPEN_ID_TYPE_PERSISTENT_ID (1) #define OPEN_ID_TYPE_PERSISTENT_ID (1)
static void __open_id_set(struct ksmbd_file *fp, unsigned int id, int type) static void __open_id_set(struct ksmbd_file *fp, u64 id, int type)
{ {
if (type == OPEN_ID_TYPE_VOLATILE_ID) if (type == OPEN_ID_TYPE_VOLATILE_ID)
fp->volatile_id = id; fp->volatile_id = id;
...@@ -505,7 +505,7 @@ static void __open_id_set(struct ksmbd_file *fp, unsigned int id, int type) ...@@ -505,7 +505,7 @@ static void __open_id_set(struct ksmbd_file *fp, unsigned int id, int type)
static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp, static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
int type) int type)
{ {
unsigned int id = 0; u64 id = 0;
int ret; int ret;
if (type == OPEN_ID_TYPE_VOLATILE_ID && fd_limit_depleted()) { if (type == OPEN_ID_TYPE_VOLATILE_ID && fd_limit_depleted()) {
...@@ -515,7 +515,7 @@ static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp, ...@@ -515,7 +515,7 @@ static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
idr_preload(GFP_KERNEL); idr_preload(GFP_KERNEL);
write_lock(&ft->lock); write_lock(&ft->lock);
ret = idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX, GFP_NOWAIT); ret = idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX - 1, GFP_NOWAIT);
if (ret >= 0) { if (ret >= 0) {
id = ret; id = ret;
ret = 0; ret = 0;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#define FILE_GENERIC_EXECUTE 0X1200a0 #define FILE_GENERIC_EXECUTE 0X1200a0
#define KSMBD_START_FID 0 #define KSMBD_START_FID 0
#define KSMBD_NO_FID (UINT_MAX) #define KSMBD_NO_FID (INT_MAX)
#define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL) #define SMB2_NO_FID (0xFFFFFFFFFFFFFFFFULL)
struct ksmbd_conn; struct ksmbd_conn;
...@@ -62,8 +62,8 @@ struct ksmbd_inode { ...@@ -62,8 +62,8 @@ struct ksmbd_inode {
struct ksmbd_file { struct ksmbd_file {
struct file *filp; struct file *filp;
char *filename; char *filename;
unsigned int persistent_id; u64 persistent_id;
unsigned int volatile_id; u64 volatile_id;
spinlock_t f_lock; spinlock_t f_lock;
...@@ -122,10 +122,8 @@ struct ksmbd_file_table { ...@@ -122,10 +122,8 @@ struct ksmbd_file_table {
struct idr *idr; struct idr *idr;
}; };
static inline bool HAS_FILE_ID(unsigned long long req) static inline bool has_file_id(u64 id)
{ {
unsigned int id = (unsigned int)req;
return id < KSMBD_NO_FID; return id < KSMBD_NO_FID;
} }
...@@ -136,11 +134,11 @@ static inline bool ksmbd_stream_fd(struct ksmbd_file *fp) ...@@ -136,11 +134,11 @@ static inline bool ksmbd_stream_fd(struct ksmbd_file *fp)
int ksmbd_init_file_table(struct ksmbd_file_table *ft); int ksmbd_init_file_table(struct ksmbd_file_table *ft);
void ksmbd_destroy_file_table(struct ksmbd_file_table *ft); void ksmbd_destroy_file_table(struct ksmbd_file_table *ft);
int ksmbd_close_fd(struct ksmbd_work *work, unsigned int id); int ksmbd_close_fd(struct ksmbd_work *work, u64 id);
struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, unsigned int id); struct ksmbd_file *ksmbd_lookup_fd_fast(struct ksmbd_work *work, u64 id);
struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, unsigned int id); struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id);
struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, unsigned int id, struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
unsigned int pid); u64 pid);
void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment