mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
hardening updates for v6.8-rc1
- Introduce the param_unknown_fn type and other clean ups (Andy Shevchenko) - Various __counted_by annotations (Christophe JAILLET, Gustavo A. R. Silva, Kees Cook) - Add KFENCE test to LKDTM (Stephen Boyd) - Various strncpy() refactorings (Justin Stitt) - Fix qnx4 to avoid writing into the smaller of two overlapping buffers - Various strlcpy() refactorings -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEEpcP2jyKd1g9yPm4TiXL039xtwCYFAmWcOsQWHGtlZXNjb29r QGNocm9taXVtLm9yZwAKCRCJcvTf3G3AJoiDD/9gNhalNG+6MNF5TDwSvO9X7pvL bQ6D3clByRxYjnJ4dMQ7p3s+rJ937uQt9PezIWHgRoldjQy3x7AJ5BxkhjeMlD2B YLbfdVYPy09X0Ewk1Efvfm/ta6tJpBGYF7Bc7LIneZrdQ6gemBpLW1PNZAFYzcWX oDjV+M1NytxaiF0aebxPZvZ1W+NGQ105Sxvj5MheDoezyO/j0CTe+ZYtCzFguFY0 8SPpR5FG4AFidb8GHd5Ndv0trVWjF1jat0FUFgEFOCE0fJNWLVR0Bbr2MtXiG7wL LF7IZ/Mn+mi+O3BmcD6JiaYf9EPlMUXCyqc8NvsnoWGqhWhWmQPCInZVrpplMUNK V/UHVMkmjDs4f/lAHBJoJHDK6fmOD+cAFaNMOltfErcjV4s+lEo6vHoiKl8hfPnH EzpQaK3funGroVYwTc35e07NrJJHCzqIUhZ0FJO7ByuOE2tIomiVo9Xy9gy54iCT qzC7zkrZ0MKqui4qiUY9FWayRRYLX4qNxELm4yie6Pzmk8943hNOaDofcyKWuZFC eqvhIkvqb4LasLrzCBk+ehA2KWSRmTrR6E9IygwbBXUTsvn2yj2RRYeAlGQNBTBZ adgSXQpRBmtKYqyihWLhP4QcunknEiQdDS3lS2qJmPH33Iv3jGH4yS6BNIBufMGL PoC2UxSfGd+YT079fw== =1Wxx -----END PGP SIGNATURE----- Merge tag 'hardening-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux Pull hardening updates from Kees Cook: - Introduce the param_unknown_fn type and other clean ups (Andy Shevchenko) - Various __counted_by annotations (Christophe JAILLET, Gustavo A. R. Silva, Kees Cook) - Add KFENCE test to LKDTM (Stephen Boyd) - Various strncpy() refactorings (Justin Stitt) - Fix qnx4 to avoid writing into the smaller of two overlapping buffers - Various strlcpy() refactorings * tag 'hardening-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: qnx4: Use get_directory_fname() in qnx4_match() qnx4: Extract dir entry filename processing into helper atags_proc: Add __counted_by for struct buffer and use struct_size() tracing/uprobe: Replace strlcpy() with strscpy() params: Fix multi-line comment style params: Sort headers params: Use size_add() for kmalloc() params: Do not go over the limit when getting the string length params: Introduce the param_unknown_fn type lkdtm: Add kfence read after free crash type nvme-fc: replace deprecated strncpy with strscpy nvdimm/btt: replace deprecated strncpy with strscpy nvme-fabrics: replace deprecated strncpy with strscpy drm/modes: replace deprecated strncpy with strscpy_pad afs: Add __counted_by for struct afs_acl and use struct_size() VMCI: Annotate struct vmci_handle_arr with __counted_by i40e: Annotate struct i40e_qvlist_info with __counted_by HID: uhid: replace deprecated strncpy with strscpy samples: Replace strlcpy() with strscpy() SUNRPC: Replace strlcpy() with strscpy()
This commit is contained in:
commit
120a201bd2
@ -7,7 +7,7 @@
|
||||
|
||||
struct buffer {
|
||||
size_t size;
|
||||
char data[];
|
||||
char data[] __counted_by(size);
|
||||
};
|
||||
|
||||
static ssize_t atags_read(struct file *file, char __user *buf,
|
||||
@ -54,7 +54,7 @@ static int __init init_atags_procfs(void)
|
||||
|
||||
WARN_ON(tag->hdr.tag != ATAG_NONE);
|
||||
|
||||
b = kmalloc(sizeof(*b) + size, GFP_KERNEL);
|
||||
b = kmalloc(struct_size(b, data, size), GFP_KERNEL);
|
||||
if (!b)
|
||||
goto nomem;
|
||||
|
||||
|
@ -2617,8 +2617,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
|
||||
out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
|
||||
strscpy_pad(out->name, in->name, sizeof(out->name));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2659,8 +2658,7 @@ int drm_mode_convert_umode(struct drm_device *dev,
|
||||
* useful for the kernel->userspace direction anyway.
|
||||
*/
|
||||
out->type = in->type & DRM_MODE_TYPE_ALL;
|
||||
strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
|
||||
out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
|
||||
strscpy_pad(out->name, in->name, sizeof(out->name));
|
||||
|
||||
/* Clearing picture aspect ratio bits from out flags,
|
||||
* as the aspect-ratio information is not stored in
|
||||
|
@ -490,7 +490,7 @@ static int uhid_dev_create2(struct uhid_device *uhid,
|
||||
const struct uhid_event *ev)
|
||||
{
|
||||
struct hid_device *hid;
|
||||
size_t rd_size, len;
|
||||
size_t rd_size;
|
||||
void *rd_data;
|
||||
int ret;
|
||||
|
||||
@ -514,13 +514,12 @@ static int uhid_dev_create2(struct uhid_device *uhid,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* @hid is zero-initialized, strncpy() is correct, strlcpy() not */
|
||||
len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1;
|
||||
strncpy(hid->name, ev->u.create2.name, len);
|
||||
len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1;
|
||||
strncpy(hid->phys, ev->u.create2.phys, len);
|
||||
len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1;
|
||||
strncpy(hid->uniq, ev->u.create2.uniq, len);
|
||||
BUILD_BUG_ON(sizeof(hid->name) != sizeof(ev->u.create2.name));
|
||||
strscpy(hid->name, ev->u.create2.name, sizeof(hid->name));
|
||||
BUILD_BUG_ON(sizeof(hid->phys) != sizeof(ev->u.create2.phys));
|
||||
strscpy(hid->phys, ev->u.create2.phys, sizeof(hid->phys));
|
||||
BUILD_BUG_ON(sizeof(hid->uniq) != sizeof(ev->u.create2.uniq));
|
||||
strscpy(hid->uniq, ev->u.create2.uniq, sizeof(hid->uniq));
|
||||
|
||||
hid->ll_driver = &uhid_hid_driver;
|
||||
hid->bus = ev->u.create2.bus;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* page allocation and slab allocations.
|
||||
*/
|
||||
#include "lkdtm.h"
|
||||
#include <linux/kfence.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/sched.h>
|
||||
@ -132,6 +133,64 @@ static void lkdtm_READ_AFTER_FREE(void)
|
||||
kfree(val);
|
||||
}
|
||||
|
||||
static void lkdtm_KFENCE_READ_AFTER_FREE(void)
|
||||
{
|
||||
int *base, val, saw;
|
||||
unsigned long timeout, resched_after;
|
||||
size_t len = 1024;
|
||||
/*
|
||||
* The slub allocator will use the either the first word or
|
||||
* the middle of the allocation to store the free pointer,
|
||||
* depending on configurations. Store in the second word to
|
||||
* avoid running into the freelist.
|
||||
*/
|
||||
size_t offset = sizeof(*base);
|
||||
|
||||
/*
|
||||
* 100x the sample interval should be more than enough to ensure we get
|
||||
* a KFENCE allocation eventually.
|
||||
*/
|
||||
timeout = jiffies + msecs_to_jiffies(100 * kfence_sample_interval);
|
||||
/*
|
||||
* Especially for non-preemption kernels, ensure the allocation-gate
|
||||
* timer can catch up: after @resched_after, every failed allocation
|
||||
* attempt yields, to ensure the allocation-gate timer is scheduled.
|
||||
*/
|
||||
resched_after = jiffies + msecs_to_jiffies(kfence_sample_interval);
|
||||
do {
|
||||
base = kmalloc(len, GFP_KERNEL);
|
||||
if (!base) {
|
||||
pr_err("FAIL: Unable to allocate kfence memory!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_kfence_address(base)) {
|
||||
val = 0x12345678;
|
||||
base[offset] = val;
|
||||
pr_info("Value in memory before free: %x\n", base[offset]);
|
||||
|
||||
kfree(base);
|
||||
|
||||
pr_info("Attempting bad read from freed memory\n");
|
||||
saw = base[offset];
|
||||
if (saw != val) {
|
||||
/* Good! Poisoning happened, so declare a win. */
|
||||
pr_info("Memory correctly poisoned (%x)\n", saw);
|
||||
} else {
|
||||
pr_err("FAIL: Memory was not poisoned!\n");
|
||||
pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
kfree(base);
|
||||
if (time_after(jiffies, resched_after))
|
||||
cond_resched();
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
pr_err("FAIL: kfence memory never allocated!\n");
|
||||
}
|
||||
|
||||
static void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
|
||||
{
|
||||
unsigned long p = __get_free_page(GFP_KERNEL);
|
||||
@ -327,6 +386,7 @@ static struct crashtype crashtypes[] = {
|
||||
CRASHTYPE(VMALLOC_LINEAR_OVERFLOW),
|
||||
CRASHTYPE(WRITE_AFTER_FREE),
|
||||
CRASHTYPE(READ_AFTER_FREE),
|
||||
CRASHTYPE(KFENCE_READ_AFTER_FREE),
|
||||
CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
|
||||
CRASHTYPE(READ_BUDDY_AFTER_FREE),
|
||||
CRASHTYPE(SLAB_INIT_ON_ALLOC),
|
||||
|
@ -17,7 +17,7 @@ struct vmci_handle_arr {
|
||||
u32 max_capacity;
|
||||
u32 size;
|
||||
u32 pad;
|
||||
struct vmci_handle entries[];
|
||||
struct vmci_handle entries[] __counted_by(capacity);
|
||||
};
|
||||
|
||||
#define VMCI_HANDLE_ARRAY_HEADER_SIZE \
|
||||
|
@ -986,7 +986,7 @@ static int btt_arena_write_layout(struct arena_info *arena)
|
||||
if (!super)
|
||||
return -ENOMEM;
|
||||
|
||||
strncpy(super->signature, BTT_SIG, BTT_SIG_LEN);
|
||||
strscpy(super->signature, BTT_SIG, sizeof(super->signature));
|
||||
export_uuid(super->uuid, nd_btt->uuid);
|
||||
export_uuid(super->parent_uuid, parent_uuid);
|
||||
super->flags = cpu_to_le32(arena->flags);
|
||||
|
@ -387,8 +387,8 @@ static struct nvmf_connect_data *nvmf_connect_data_prep(struct nvme_ctrl *ctrl,
|
||||
|
||||
uuid_copy(&data->hostid, &ctrl->opts->host->id);
|
||||
data->cntlid = cpu_to_le16(cntlid);
|
||||
strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
|
||||
strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
|
||||
strscpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
|
||||
strscpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -1218,10 +1218,10 @@ nvme_fc_connect_admin_queue(struct nvme_fc_ctrl *ctrl,
|
||||
/* Linux supports only Dynamic controllers */
|
||||
assoc_rqst->assoc_cmd.cntlid = cpu_to_be16(0xffff);
|
||||
uuid_copy(&assoc_rqst->assoc_cmd.hostid, &ctrl->ctrl.opts->host->id);
|
||||
strncpy(assoc_rqst->assoc_cmd.hostnqn, ctrl->ctrl.opts->host->nqn,
|
||||
min(FCNVME_ASSOC_HOSTNQN_LEN, NVMF_NQN_SIZE));
|
||||
strncpy(assoc_rqst->assoc_cmd.subnqn, ctrl->ctrl.opts->subsysnqn,
|
||||
min(FCNVME_ASSOC_SUBNQN_LEN, NVMF_NQN_SIZE));
|
||||
strscpy(assoc_rqst->assoc_cmd.hostnqn, ctrl->ctrl.opts->host->nqn,
|
||||
sizeof(assoc_rqst->assoc_cmd.hostnqn));
|
||||
strscpy(assoc_rqst->assoc_cmd.subnqn, ctrl->ctrl.opts->subsysnqn,
|
||||
sizeof(assoc_rqst->assoc_cmd.subnqn));
|
||||
|
||||
lsop->queue = queue;
|
||||
lsreq->rqstaddr = assoc_rqst;
|
||||
|
@ -1213,7 +1213,7 @@ extern void afs_fs_inline_bulk_status(struct afs_operation *);
|
||||
|
||||
struct afs_acl {
|
||||
u32 size;
|
||||
u8 data[];
|
||||
u8 data[] __counted_by(size);
|
||||
};
|
||||
|
||||
extern void afs_fs_fetch_acl(struct afs_operation *);
|
||||
|
@ -75,7 +75,7 @@ static bool afs_make_acl(struct afs_operation *op,
|
||||
{
|
||||
struct afs_acl *acl;
|
||||
|
||||
acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
|
||||
acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
|
||||
if (!acl) {
|
||||
afs_op_nomem(op);
|
||||
return false;
|
||||
|
@ -15,43 +15,6 @@
|
||||
#include <linux/buffer_head.h>
|
||||
#include "qnx4.h"
|
||||
|
||||
/*
|
||||
* A qnx4 directory entry is an inode entry or link info
|
||||
* depending on the status field in the last byte. The
|
||||
* first byte is where the name start either way, and a
|
||||
* zero means it's empty.
|
||||
*
|
||||
* Also, due to a bug in gcc, we don't want to use the
|
||||
* real (differently sized) name arrays in the inode and
|
||||
* link entries, but always the 'de_name[]' one in the
|
||||
* fake struct entry.
|
||||
*
|
||||
* See
|
||||
*
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c6
|
||||
*
|
||||
* for details, but basically gcc will take the size of the
|
||||
* 'name' array from one of the used union entries randomly.
|
||||
*
|
||||
* This use of 'de_name[]' (48 bytes) avoids the false positive
|
||||
* warnings that would happen if gcc decides to use 'inode.di_name'
|
||||
* (16 bytes) even when the pointer and size were to come from
|
||||
* 'link.dl_name' (48 bytes).
|
||||
*
|
||||
* In all cases the actual name pointer itself is the same, it's
|
||||
* only the gcc internal 'what is the size of this field' logic
|
||||
* that can get confused.
|
||||
*/
|
||||
union qnx4_directory_entry {
|
||||
struct {
|
||||
const char de_name[48];
|
||||
u8 de_pad[15];
|
||||
u8 de_status;
|
||||
};
|
||||
struct qnx4_inode_entry inode;
|
||||
struct qnx4_link_info link;
|
||||
};
|
||||
|
||||
static int qnx4_readdir(struct file *file, struct dir_context *ctx)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
@ -74,26 +37,25 @@ static int qnx4_readdir(struct file *file, struct dir_context *ctx)
|
||||
ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK;
|
||||
for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) {
|
||||
union qnx4_directory_entry *de;
|
||||
const char *fname;
|
||||
|
||||
offset = ix * QNX4_DIR_ENTRY_SIZE;
|
||||
de = (union qnx4_directory_entry *) (bh->b_data + offset);
|
||||
|
||||
if (!de->de_name[0])
|
||||
continue;
|
||||
if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK)))
|
||||
fname = get_entry_fname(de, &size);
|
||||
if (!fname)
|
||||
continue;
|
||||
|
||||
if (!(de->de_status & QNX4_FILE_LINK)) {
|
||||
size = sizeof(de->inode.di_fname);
|
||||
ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
|
||||
} else {
|
||||
size = sizeof(de->link.dl_fname);
|
||||
ino = ( le32_to_cpu(de->link.dl_inode_blk) - 1 ) *
|
||||
QNX4_INODES_PER_BLOCK +
|
||||
de->link.dl_inode_ndx;
|
||||
}
|
||||
size = strnlen(de->de_name, size);
|
||||
QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, name));
|
||||
if (!dir_emit(ctx, de->de_name, size, ino, DT_UNKNOWN)) {
|
||||
|
||||
QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, fname));
|
||||
if (!dir_emit(ctx, fname, size, ino, DT_UNKNOWN)) {
|
||||
brelse(bh);
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,31 +26,24 @@
|
||||
static int qnx4_match(int len, const char *name,
|
||||
struct buffer_head *bh, unsigned long *offset)
|
||||
{
|
||||
struct qnx4_inode_entry *de;
|
||||
int namelen, thislen;
|
||||
union qnx4_directory_entry *de;
|
||||
const char *fname;
|
||||
int fnamelen;
|
||||
|
||||
if (bh == NULL) {
|
||||
printk(KERN_WARNING "qnx4: matching unassigned buffer !\n");
|
||||
return 0;
|
||||
}
|
||||
de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
|
||||
de = (union qnx4_directory_entry *) (bh->b_data + *offset);
|
||||
*offset += QNX4_DIR_ENTRY_SIZE;
|
||||
if ((de->di_status & QNX4_FILE_LINK) != 0) {
|
||||
namelen = QNX4_NAME_MAX;
|
||||
} else {
|
||||
namelen = QNX4_SHORT_NAME_MAX;
|
||||
}
|
||||
thislen = strlen( de->di_fname );
|
||||
if ( thislen > namelen )
|
||||
thislen = namelen;
|
||||
if (len != thislen) {
|
||||
|
||||
fname = get_entry_fname(de, &fnamelen);
|
||||
if (!fname || len != fnamelen)
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(name, de->di_fname, len) == 0) {
|
||||
if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(name, fname, len) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -44,3 +44,63 @@ static inline struct qnx4_inode_entry *qnx4_raw_inode(struct inode *inode)
|
||||
{
|
||||
return &qnx4_i(inode)->raw;
|
||||
}
|
||||
|
||||
/*
|
||||
* A qnx4 directory entry is an inode entry or link info
|
||||
* depending on the status field in the last byte. The
|
||||
* first byte is where the name start either way, and a
|
||||
* zero means it's empty.
|
||||
*
|
||||
* Also, due to a bug in gcc, we don't want to use the
|
||||
* real (differently sized) name arrays in the inode and
|
||||
* link entries, but always the 'de_name[]' one in the
|
||||
* fake struct entry.
|
||||
*
|
||||
* See
|
||||
*
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c6
|
||||
*
|
||||
* for details, but basically gcc will take the size of the
|
||||
* 'name' array from one of the used union entries randomly.
|
||||
*
|
||||
* This use of 'de_name[]' (48 bytes) avoids the false positive
|
||||
* warnings that would happen if gcc decides to use 'inode.di_name'
|
||||
* (16 bytes) even when the pointer and size were to come from
|
||||
* 'link.dl_name' (48 bytes).
|
||||
*
|
||||
* In all cases the actual name pointer itself is the same, it's
|
||||
* only the gcc internal 'what is the size of this field' logic
|
||||
* that can get confused.
|
||||
*/
|
||||
union qnx4_directory_entry {
|
||||
struct {
|
||||
const char de_name[48];
|
||||
u8 de_pad[15];
|
||||
u8 de_status;
|
||||
};
|
||||
struct qnx4_inode_entry inode;
|
||||
struct qnx4_link_info link;
|
||||
};
|
||||
|
||||
static inline const char *get_entry_fname(union qnx4_directory_entry *de,
|
||||
int *size)
|
||||
{
|
||||
/* Make sure the status byte is in the same place for all structs. */
|
||||
BUILD_BUG_ON(offsetof(struct qnx4_inode_entry, di_status) !=
|
||||
offsetof(struct qnx4_link_info, dl_status));
|
||||
BUILD_BUG_ON(offsetof(struct qnx4_inode_entry, di_status) !=
|
||||
offsetof(union qnx4_directory_entry, de_status));
|
||||
|
||||
if (!de->de_name[0])
|
||||
return NULL;
|
||||
if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK)))
|
||||
return NULL;
|
||||
if (!(de->de_status & QNX4_FILE_LINK))
|
||||
*size = sizeof(de->inode.di_fname);
|
||||
else
|
||||
*size = sizeof(de->link.dl_fname);
|
||||
|
||||
*size = strnlen(de->de_name, *size);
|
||||
|
||||
return de->de_name;
|
||||
}
|
||||
|
@ -223,6 +223,8 @@ bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *sla
|
||||
|
||||
#else /* CONFIG_KFENCE */
|
||||
|
||||
#define kfence_sample_interval (0)
|
||||
|
||||
static inline bool is_kfence_address(const void *addr) { return false; }
|
||||
static inline void kfence_alloc_pool_and_metadata(void) { }
|
||||
static inline void kfence_init(void) { }
|
||||
|
@ -385,6 +385,8 @@ extern bool parameq(const char *name1, const char *name2);
|
||||
*/
|
||||
extern bool parameqn(const char *name1, const char *name2, size_t n);
|
||||
|
||||
typedef int (*parse_unknown_fn)(char *param, char *val, const char *doing, void *arg);
|
||||
|
||||
/* Called on module insert or kernel boot */
|
||||
extern char *parse_args(const char *name,
|
||||
char *args,
|
||||
@ -392,9 +394,7 @@ extern char *parse_args(const char *name,
|
||||
unsigned num,
|
||||
s16 level_min,
|
||||
s16 level_max,
|
||||
void *arg,
|
||||
int (*unknown)(char *param, char *val,
|
||||
const char *doing, void *arg));
|
||||
void *arg, parse_unknown_fn unknown);
|
||||
|
||||
/* Called by module remove. */
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
@ -45,7 +45,7 @@ struct i40e_qv_info {
|
||||
|
||||
struct i40e_qvlist_info {
|
||||
u32 num_vectors;
|
||||
struct i40e_qv_info qv_info[];
|
||||
struct i40e_qv_info qv_info[] __counted_by(num_vectors);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,19 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Helpers for initial module or kernel cmdline parsing
|
||||
Copyright (C) 2001 Rusty Russell.
|
||||
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
/*
|
||||
* Helpers for initial module or kernel cmdline parsing
|
||||
* Copyright (C) 2001 Rusty Russell.
|
||||
*/
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
/* Protects all built-in parameters, modules use their own param_lock */
|
||||
@ -48,7 +49,7 @@ static void *kmalloc_parameter(unsigned int size)
|
||||
{
|
||||
struct kmalloced_param *p;
|
||||
|
||||
p = kmalloc(sizeof(*p) + size, GFP_KERNEL);
|
||||
p = kmalloc(size_add(sizeof(*p), size), GFP_KERNEL);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
@ -120,9 +121,7 @@ static int parse_one(char *param,
|
||||
unsigned num_params,
|
||||
s16 min_level,
|
||||
s16 max_level,
|
||||
void *arg,
|
||||
int (*handle_unknown)(char *param, char *val,
|
||||
const char *doing, void *arg))
|
||||
void *arg, parse_unknown_fn handle_unknown)
|
||||
{
|
||||
unsigned int i;
|
||||
int err;
|
||||
@ -165,9 +164,7 @@ char *parse_args(const char *doing,
|
||||
unsigned num,
|
||||
s16 min_level,
|
||||
s16 max_level,
|
||||
void *arg,
|
||||
int (*unknown)(char *param, char *val,
|
||||
const char *doing, void *arg))
|
||||
void *arg, parse_unknown_fn unknown)
|
||||
{
|
||||
char *param, *val, *err = NULL;
|
||||
|
||||
@ -264,17 +261,22 @@ EXPORT_SYMBOL_GPL(param_set_uint_minmax);
|
||||
|
||||
int param_set_charp(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
if (strlen(val) > 1024) {
|
||||
size_t len, maxlen = 1024;
|
||||
|
||||
len = strnlen(val, maxlen + 1);
|
||||
if (len == maxlen + 1) {
|
||||
pr_err("%s: string parameter too long\n", kp->name);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
maybe_kfree_parameter(*(char **)kp->arg);
|
||||
|
||||
/* This is a hack. We can't kmalloc in early boot, and we
|
||||
* don't need to; this mangled commandline is preserved. */
|
||||
/*
|
||||
* This is a hack. We can't kmalloc() in early boot, and we
|
||||
* don't need to; this mangled commandline is preserved.
|
||||
*/
|
||||
if (slab_is_available()) {
|
||||
*(char **)kp->arg = kmalloc_parameter(strlen(val)+1);
|
||||
*(char **)kp->arg = kmalloc_parameter(len + 1);
|
||||
if (!*(char **)kp->arg)
|
||||
return -ENOMEM;
|
||||
strcpy(*(char **)kp->arg, val);
|
||||
@ -512,7 +514,7 @@ int param_set_copystring(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
const struct kparam_string *kps = kp->str;
|
||||
|
||||
if (strlen(val)+1 > kps->maxlen) {
|
||||
if (strnlen(val, kps->maxlen) == kps->maxlen) {
|
||||
pr_err("%s: string doesn't fit in %u chars.\n",
|
||||
kp->name, kps->maxlen-1);
|
||||
return -ENOSPC;
|
||||
@ -743,8 +745,10 @@ void module_param_sysfs_remove(struct module *mod)
|
||||
{
|
||||
if (mod->mkobj.mp) {
|
||||
sysfs_remove_group(&mod->mkobj.kobj, &mod->mkobj.mp->grp);
|
||||
/* We are positive that no one is using any param
|
||||
* attrs at this point. Deallocate immediately. */
|
||||
/*
|
||||
* We are positive that no one is using any param
|
||||
* attrs at this point. Deallocate immediately.
|
||||
*/
|
||||
free_module_param_attrs(&mod->mkobj);
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
|
||||
return -ENOMEM;
|
||||
|
||||
if (addr == FETCH_TOKEN_COMM)
|
||||
ret = strlcpy(dst, current->comm, maxlen);
|
||||
ret = strscpy(dst, current->comm, maxlen);
|
||||
else
|
||||
ret = strncpy_from_user(dst, src, maxlen);
|
||||
if (ret >= 0) {
|
||||
|
@ -287,8 +287,14 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
|
||||
|
||||
static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
|
||||
{
|
||||
clnt->cl_nodelen = strlcpy(clnt->cl_nodename,
|
||||
nodename, sizeof(clnt->cl_nodename));
|
||||
ssize_t copied;
|
||||
|
||||
copied = strscpy(clnt->cl_nodename,
|
||||
nodename, sizeof(clnt->cl_nodename));
|
||||
|
||||
clnt->cl_nodelen = copied < 0
|
||||
? sizeof(clnt->cl_nodename) - 1
|
||||
: copied;
|
||||
}
|
||||
|
||||
static int rpc_client_register(struct rpc_clnt *clnt,
|
||||
|
@ -305,7 +305,7 @@ TRACE_EVENT(foo_bar,
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
strlcpy(__entry->foo, foo, 10);
|
||||
strscpy(__entry->foo, foo, 10);
|
||||
__entry->bar = bar;
|
||||
memcpy(__get_dynamic_array(list), lst,
|
||||
__length_of(lst) * sizeof(int));
|
||||
|
@ -291,8 +291,8 @@ static int skeleton_querycap(struct file *file, void *priv,
|
||||
{
|
||||
struct skeleton *skel = video_drvdata(file);
|
||||
|
||||
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
||||
strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card));
|
||||
strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
||||
strscpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card));
|
||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
|
||||
pci_name(skel->pdev));
|
||||
return 0;
|
||||
@ -597,11 +597,11 @@ static int skeleton_enum_input(struct file *file, void *priv,
|
||||
i->type = V4L2_INPUT_TYPE_CAMERA;
|
||||
if (i->index == 0) {
|
||||
i->std = SKEL_TVNORMS;
|
||||
strlcpy(i->name, "S-Video", sizeof(i->name));
|
||||
strscpy(i->name, "S-Video", sizeof(i->name));
|
||||
i->capabilities = V4L2_IN_CAP_STD;
|
||||
} else {
|
||||
i->std = 0;
|
||||
strlcpy(i->name, "HDMI", sizeof(i->name));
|
||||
strscpy(i->name, "HDMI", sizeof(i->name));
|
||||
i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
|
||||
}
|
||||
return 0;
|
||||
@ -845,7 +845,7 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
/* Initialize the video_device structure */
|
||||
vdev = &skel->vdev;
|
||||
strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
|
||||
strscpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
|
||||
/*
|
||||
* There is nothing to clean up, so release is set to an empty release
|
||||
* function. The release callback must be non-NULL.
|
||||
|
Loading…
Reference in New Issue
Block a user