Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_generic.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/ktr.h> | #include <sys/ktr.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/poll.h> | #include <sys/poll.h> | ||||
#include <sys/resourcevar.h> | #include <sys/resourcevar.h> | ||||
#include <sys/selinfo.h> | #include <sys/selinfo.h> | ||||
#include <sys/sleepqueue.h> | #include <sys/sleepqueue.h> | ||||
#include <sys/stat.h> | |||||
#include <sys/syscallsubr.h> | #include <sys/syscallsubr.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/sysent.h> | #include <sys/sysent.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/condvar.h> | #include <sys/condvar.h> | ||||
#ifdef KTRACE | #ifdef KTRACE | ||||
▲ Show 20 Lines • Show All 516 Lines • ▼ Show 20 Lines | |||||
* Truncate a file given a file descriptor. | * Truncate a file given a file descriptor. | ||||
* | * | ||||
* Can't use fget_write() here, since must return EINVAL and not EBADF if the | * Can't use fget_write() here, since must return EINVAL and not EBADF if the | ||||
* descriptor isn't writable. | * descriptor isn't writable. | ||||
*/ | */ | ||||
int | int | ||||
kern_ftruncate(struct thread *td, int fd, off_t length) | kern_ftruncate(struct thread *td, int fd, off_t length) | ||||
{ | { | ||||
struct stat sb; | |||||
struct file *fp; | struct file *fp; | ||||
int error; | int error, seals; | ||||
AUDIT_ARG_FD(fd); | AUDIT_ARG_FD(fd); | ||||
if (length < 0) | if (length < 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
error = fget(td, fd, &cap_ftruncate_rights, &fp); | error = fget(td, fd, &cap_ftruncate_rights, &fp); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
AUDIT_ARG_FILE(td->td_proc, fp); | AUDIT_ARG_FILE(td->td_proc, fp); | ||||
if (!(fp->f_flag & FWRITE)) { | if (!(fp->f_flag & FWRITE)) { | ||||
fdrop(fp, td); | error = EINVAL; | ||||
return (EINVAL); | goto out; | ||||
} | } | ||||
/* | |||||
kib: Why do we need to expose seals to the file level ? I would prefer, and actually think that it… | |||||
Done Inline ActionsWhoops. I would think you're correct... if we do something like: int fd, fdx; char buf[8]; fd = memfd_create("...", MFD_ALLOW_SEALING); fdx = dup(fd); fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_SEAL); write(fdx, buf, sizeof(buf)); I would expect the write to fdx to fail because we're supposed to apply seals at the inode level, so revoking CAP_WRITE from fd isn't sufficient and likewise for ftruncate bits... I'll push it down a bit further into shm_dotruncate and shm_write and make it all return EPERM like Linux implementation. kevans: Whoops. I would think you're correct... if we do something like:
```
int fd, fdx;
char buf[8]… | |||||
* ftruncate being completely sealed is already handled by revoking the | |||||
* ftruncate capability completely. Here we only have to handle the | |||||
* case of either restricted shrink or restricted growth, but not both. | |||||
*/ | |||||
if (fo_get_seals(fp, &seals) == 0 && (seals & F_SEAL_TRUNCATE) != 0) { | |||||
error = fo_stat(fp, &sb, td->td_ucred, td); | |||||
if (error == 0) { | |||||
if (length < sb.st_size && | |||||
(seals & F_SEAL_SHRINK) != 0) { | |||||
error = ENOTCAPABLE; | |||||
goto out; | |||||
} else if (length > sb.st_size && | |||||
(seals & F_SEAL_GROW) != 0) { | |||||
error = ENOTCAPABLE; | |||||
goto out; | |||||
} | |||||
} | |||||
} | |||||
error = fo_truncate(fp, length, td->td_ucred, td); | error = fo_truncate(fp, length, td->td_ucred, td); | ||||
out: | |||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct ftruncate_args { | struct ftruncate_args { | ||||
int fd; | int fd; | ||||
int pad; | int pad; | ||||
▲ Show 20 Lines • Show All 1,257 Lines • Show Last 20 Lines |
Why do we need to expose seals to the file level ? I would prefer, and actually think that it is required, that seals handling should be done by the file type itself. In other words, it should be shmfd business,