diff options
| author | John Baldwin <jhb@FreeBSD.org> | 2026-03-17 19:45:34 +0000 |
|---|---|---|
| committer | John Baldwin <jhb@FreeBSD.org> | 2026-03-17 19:45:34 +0000 |
| commit | 2cf15144daf7ec44cdcd9bf3ef007939b79c361e (patch) | |
| tree | 931c84bfeb0d37d569716ee0938db43e6bb052aa /sys/compat/linuxkpi/common | |
| parent | 14e97448fcebbe4b038eaf5628933abe5f9e690d (diff) | |
Diffstat (limited to 'sys/compat/linuxkpi/common')
| -rw-r--r-- | sys/compat/linuxkpi/common/include/linux/fs.h | 28 | ||||
| -rw-r--r-- | sys/compat/linuxkpi/common/include/linux/seq_file.h | 2 | ||||
| -rw-r--r-- | sys/compat/linuxkpi/common/src/linux_seq_file.c | 2 | ||||
| -rw-r--r-- | sys/compat/linuxkpi/common/src/linux_simple_attr.c | 35 |
4 files changed, 38 insertions, 29 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h index f1568ad6282d..40e1b396fe86 100644 --- a/sys/compat/linuxkpi/common/include/linux/fs.h +++ b/sys/compat/linuxkpi/common/include/linux/fs.h @@ -364,8 +364,9 @@ static inline ssize_t simple_read_from_buffer(void __user *dest, size_t read_size, loff_t *ppos, void *orig, size_t buf_size) { - void *p, *read_pos = ((char *) orig) + *ppos; + void *read_pos = ((char *) orig) + *ppos; size_t buf_remain = buf_size - *ppos; + ssize_t num_read; if (buf_remain < 0 || buf_remain > buf_size) return -EINVAL; @@ -373,18 +374,13 @@ simple_read_from_buffer(void __user *dest, size_t read_size, loff_t *ppos, if (read_size > buf_remain) read_size = buf_remain; - /* - * XXX At time of commit only debugfs consumers could be - * identified. If others will use this function we may - * have to revise this: normally we would call copy_to_user() - * here but lindebugfs will return the result and the - * copyout is done elsewhere for us. - */ - p = memcpy(dest, read_pos, read_size); - if (p != NULL) - *ppos += read_size; + /* copy_to_user returns number of bytes NOT read */ + num_read = read_size - copy_to_user(dest, read_pos, read_size); + if (num_read == 0) + return -EFAULT; + *ppos += num_read; - return (read_size); + return (num_read); } MALLOC_DECLARE(M_LSATTR); @@ -415,11 +411,13 @@ int simple_attr_open(struct inode *inode, struct file *filp, int simple_attr_release(struct inode *inode, struct file *filp); -ssize_t simple_attr_read(struct file *filp, char *buf, size_t read_size, loff_t *ppos); +ssize_t simple_attr_read(struct file *filp, char __user *buf, size_t read_size, + loff_t *ppos); -ssize_t simple_attr_write(struct file *filp, const char *buf, size_t write_size, loff_t *ppos); +ssize_t simple_attr_write(struct file *filp, const char __user *buf, + size_t write_size, loff_t *ppos); -ssize_t simple_attr_write_signed(struct file *filp, const char *buf, +ssize_t simple_attr_write_signed(struct file *filp, const char __user *buf, size_t write_size, loff_t *ppos); #endif /* _LINUXKPI_LINUX_FS_H_ */ diff --git a/sys/compat/linuxkpi/common/include/linux/seq_file.h b/sys/compat/linuxkpi/common/include/linux/seq_file.h index 3c7862890c67..786c09bd6a20 100644 --- a/sys/compat/linuxkpi/common/include/linux/seq_file.h +++ b/sys/compat/linuxkpi/common/include/linux/seq_file.h @@ -85,7 +85,7 @@ struct seq_operations { int (*show) (struct seq_file *m, void *v); }; -ssize_t seq_read(struct linux_file *, char *, size_t, off_t *); +ssize_t seq_read(struct linux_file *, char __user *, size_t, off_t *); int seq_write(struct seq_file *seq, const void *data, size_t len); void seq_putc(struct seq_file *m, char c); void seq_puts(struct seq_file *m, const char *str); diff --git a/sys/compat/linuxkpi/common/src/linux_seq_file.c b/sys/compat/linuxkpi/common/src/linux_seq_file.c index b1d53aa2db60..eae414ea696e 100644 --- a/sys/compat/linuxkpi/common/src/linux_seq_file.c +++ b/sys/compat/linuxkpi/common/src/linux_seq_file.c @@ -40,7 +40,7 @@ MALLOC_DEFINE(M_LSEQ, "seq_file", "seq_file"); ssize_t -seq_read(struct linux_file *f, char *ubuf, size_t size, off_t *ppos) +seq_read(struct linux_file *f, char __user *ubuf, size_t size, off_t *ppos) { struct seq_file *m; struct sbuf *sbuf; diff --git a/sys/compat/linuxkpi/common/src/linux_simple_attr.c b/sys/compat/linuxkpi/common/src/linux_simple_attr.c index 88fa908e47bb..e5514194cb33 100644 --- a/sys/compat/linuxkpi/common/src/linux_simple_attr.c +++ b/sys/compat/linuxkpi/common/src/linux_simple_attr.c @@ -99,7 +99,8 @@ simple_attr_release(struct inode *inode, struct file *filp) * On failure, negative signed ERRNO */ ssize_t -simple_attr_read(struct file *filp, char *buf, size_t read_size, loff_t *ppos) +simple_attr_read(struct file *filp, char __user *buf, size_t read_size, + loff_t *ppos) { struct simple_attr *sattr; uint64_t data; @@ -146,29 +147,38 @@ unlock: * On failure, negative signed ERRNO */ static ssize_t -simple_attr_write_common(struct file *filp, const char *buf, size_t write_size, - loff_t *ppos, bool is_signed) +simple_attr_write_common(struct file *filp, const char __user *ubuf, + size_t write_size, loff_t *ppos, bool is_signed) { struct simple_attr *sattr; unsigned long long data; - size_t bufsize; + char *buf; ssize_t ret; sattr = filp->private_data; - bufsize = strlen(buf) + 1; if (sattr->set == NULL) return (-EFAULT); - if (*ppos >= bufsize || write_size < 1) + if (*ppos != 0 || write_size < 1) return (-EINVAL); + buf = malloc(write_size, M_LSATTR, M_WAITOK); + if (copy_from_user(buf, ubuf, write_size) != 0) { + free(buf, M_LSATTR); + return (-EFAULT); + } + if (strnlen(buf, write_size) == write_size) { + free(buf, M_LSATTR); + return (-EINVAL); + } + mutex_lock(&sattr->mutex); if (is_signed) - ret = kstrtoll(buf + *ppos, 0, &data); + ret = kstrtoll(buf, 0, &data); else - ret = kstrtoull(buf + *ppos, 0, &data); + ret = kstrtoull(buf, 0, &data); if (ret) goto unlock; @@ -176,23 +186,24 @@ simple_attr_write_common(struct file *filp, const char *buf, size_t write_size, if (ret) goto unlock; - ret = bufsize - *ppos; + ret = write_size; unlock: mutex_unlock(&sattr->mutex); + free(buf, M_LSATTR); return (ret); } ssize_t -simple_attr_write(struct file *filp, const char *buf, size_t write_size, +simple_attr_write(struct file *filp, const char __user *buf, size_t write_size, loff_t *ppos) { return (simple_attr_write_common(filp, buf, write_size, ppos, false)); } ssize_t -simple_attr_write_signed(struct file *filp, const char *buf, size_t write_size, - loff_t *ppos) +simple_attr_write_signed(struct file *filp, const char __user *buf, + size_t write_size, loff_t *ppos) { return (simple_attr_write_common(filp, buf, write_size, ppos, true)); } |
