mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 11:31:31 +00:00
the bulk of struct fd memory safety stuff
Making sure that struct fd instances are destroyed in the same scope where they'd been created, getting rid of reassignments and passing them by reference, converting to CLASS(fd{,_pos,_raw}). We are getting very close to having the memory safety of that stuff trivial to verify. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQqUNBr3gm4hGXdBJlZ7Krx/gZQ6wUCZzdikAAKCRBZ7Krx/gZQ 69nJAQCmbQHK3TGUbQhOw6MJXOK9ezpyEDN3FZb4jsu38vTIdgEA6OxAYDO2m2g9 CN18glYmD3wRyU6Bwl4vGODouSJvDgA= =gVH3 -----END PGP SIGNATURE----- Merge tag 'pull-fd' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs Pull 'struct fd' class updates from Al Viro: "The bulk of struct fd memory safety stuff Making sure that struct fd instances are destroyed in the same scope where they'd been created, getting rid of reassignments and passing them by reference, converting to CLASS(fd{,_pos,_raw}). We are getting very close to having the memory safety of that stuff trivial to verify" * tag 'pull-fd' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (28 commits) deal with the last remaing boolean uses of fd_file() css_set_fork(): switch to CLASS(fd_raw, ...) memcg_write_event_control(): switch to CLASS(fd) assorted variants of irqfd setup: convert to CLASS(fd) do_pollfd(): convert to CLASS(fd) convert do_select() convert vfs_dedupe_file_range(). convert cifs_ioctl_copychunk() convert media_request_get_by_fd() convert spu_run(2) switch spufs_calls_{get,put}() to CLASS() use convert cachestat(2) convert do_preadv()/do_pwritev() fdget(), more trivial conversions fdget(), trivial conversions privcmd_ioeventfd_assign(): don't open-code eventfd_ctx_fdget() o2hb_region_dev_store(): avoid goto around fdget()/fdput() introduce "fd_pos" class, convert fdget_pos() users to it. fdget_raw() users: switch to CLASS(fd_raw) convert vmsplice() to CLASS(fd) ...
This commit is contained in:
commit
0f25f0e4ef
@ -152,7 +152,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
|
|||||||
long __user *, basep)
|
long __user *, basep)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct fd arg = fdget_pos(fd);
|
CLASS(fd_pos, arg)(fd);
|
||||||
struct osf_dirent_callback buf = {
|
struct osf_dirent_callback buf = {
|
||||||
.ctx.actor = osf_filldir,
|
.ctx.actor = osf_filldir,
|
||||||
.dirent = dirent,
|
.dirent = dirent,
|
||||||
@ -160,7 +160,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
|
|||||||
.count = count
|
.count = count
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!fd_file(arg))
|
if (fd_empty(arg))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = iterate_dir(fd_file(arg), &buf.ctx);
|
error = iterate_dir(fd_file(arg), &buf.ctx);
|
||||||
@ -169,7 +169,6 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
|
|||||||
if (count != buf.count)
|
if (count != buf.count)
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
|
|
||||||
fdput_pos(arg);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,12 +235,12 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
|
|||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
struct fd f = fdget_raw(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
struct flock64 flock;
|
struct flock64 flock;
|
||||||
long err = -EBADF;
|
long err;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_GETLK64:
|
case F_GETLK64:
|
||||||
@ -271,8 +271,6 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
|
|||||||
err = sys_fcntl64(fd, cmd, arg);
|
err = sys_fcntl64(fd, cmd, arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +115,9 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
struct iommu_table_group *table_group;
|
struct iommu_table_group *table_group;
|
||||||
long i;
|
long i;
|
||||||
struct kvmppc_spapr_tce_iommu_table *stit;
|
struct kvmppc_spapr_tce_iommu_table *stit;
|
||||||
struct fd f;
|
CLASS(fd, f)(tablefd);
|
||||||
|
|
||||||
f = fdget(tablefd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@ -130,16 +129,12 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (!found) {
|
if (!found)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
table_group = iommu_group_get_iommudata(grp);
|
table_group = iommu_group_get_iommudata(grp);
|
||||||
if (WARN_ON(!table_group)) {
|
if (WARN_ON(!table_group))
|
||||||
fdput(f);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
|
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
|
||||||
struct iommu_table *tbltmp = table_group->tables[i];
|
struct iommu_table *tbltmp = table_group->tables[i];
|
||||||
@ -160,10 +155,8 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tbl) {
|
if (!tbl)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
|
list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
|
||||||
@ -174,7 +167,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
/* stit is being destroyed */
|
/* stit is being destroyed */
|
||||||
iommu_tce_table_put(tbl);
|
iommu_tce_table_put(tbl);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
fdput(f);
|
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -182,7 +174,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
* its KVM reference counter and can return.
|
* its KVM reference counter and can return.
|
||||||
*/
|
*/
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -190,7 +181,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
stit = kzalloc(sizeof(*stit), GFP_KERNEL);
|
stit = kzalloc(sizeof(*stit), GFP_KERNEL);
|
||||||
if (!stit) {
|
if (!stit) {
|
||||||
iommu_tce_table_put(tbl);
|
iommu_tce_table_put(tbl);
|
||||||
fdput(f);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +189,6 @@ long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
|||||||
|
|
||||||
list_add_rcu(&stit->next, &stt->iommu_tables);
|
list_add_rcu(&stit->next, &stt->iommu_tables);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1933,12 +1933,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_KVM_MPIC
|
#ifdef CONFIG_KVM_MPIC
|
||||||
case KVM_CAP_IRQ_MPIC: {
|
case KVM_CAP_IRQ_MPIC: {
|
||||||
struct fd f;
|
CLASS(fd, f)(cap->args[0]);
|
||||||
struct kvm_device *dev;
|
struct kvm_device *dev;
|
||||||
|
|
||||||
r = -EBADF;
|
r = -EBADF;
|
||||||
f = fdget(cap->args[0]);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
r = -EPERM;
|
r = -EPERM;
|
||||||
@ -1946,18 +1945,16 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
|
|||||||
if (dev)
|
if (dev)
|
||||||
r = kvmppc_mpic_connect_vcpu(dev, vcpu, cap->args[1]);
|
r = kvmppc_mpic_connect_vcpu(dev, vcpu, cap->args[1]);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_KVM_XICS
|
#ifdef CONFIG_KVM_XICS
|
||||||
case KVM_CAP_IRQ_XICS: {
|
case KVM_CAP_IRQ_XICS: {
|
||||||
struct fd f;
|
CLASS(fd, f)(cap->args[0]);
|
||||||
struct kvm_device *dev;
|
struct kvm_device *dev;
|
||||||
|
|
||||||
r = -EBADF;
|
r = -EBADF;
|
||||||
f = fdget(cap->args[0]);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
r = -EPERM;
|
r = -EPERM;
|
||||||
@ -1968,34 +1965,27 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
|
|||||||
else
|
else
|
||||||
r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
|
r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_KVM_XICS */
|
#endif /* CONFIG_KVM_XICS */
|
||||||
#ifdef CONFIG_KVM_XIVE
|
#ifdef CONFIG_KVM_XIVE
|
||||||
case KVM_CAP_PPC_IRQ_XIVE: {
|
case KVM_CAP_PPC_IRQ_XIVE: {
|
||||||
struct fd f;
|
CLASS(fd, f)(cap->args[0]);
|
||||||
struct kvm_device *dev;
|
struct kvm_device *dev;
|
||||||
|
|
||||||
r = -EBADF;
|
r = -EBADF;
|
||||||
f = fdget(cap->args[0]);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
r = -ENXIO;
|
r = -ENXIO;
|
||||||
if (!xive_enabled()) {
|
if (!xive_enabled())
|
||||||
fdput(f);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
r = -EPERM;
|
r = -EPERM;
|
||||||
dev = kvm_device_from_filp(fd_file(f));
|
dev = kvm_device_from_filp(fd_file(f));
|
||||||
if (dev)
|
if (dev)
|
||||||
r = kvmppc_xive_native_connect_vcpu(dev, vcpu,
|
r = kvmppc_xive_native_connect_vcpu(dev, vcpu,
|
||||||
cap->args[1]);
|
cap->args[1]);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_KVM_XIVE */
|
#endif /* CONFIG_KVM_XIVE */
|
||||||
|
@ -36,6 +36,9 @@ static inline struct spufs_calls *spufs_calls_get(void)
|
|||||||
|
|
||||||
static inline void spufs_calls_put(struct spufs_calls *calls)
|
static inline void spufs_calls_put(struct spufs_calls *calls)
|
||||||
{
|
{
|
||||||
|
if (!calls)
|
||||||
|
return;
|
||||||
|
|
||||||
BUG_ON(calls != spufs_calls);
|
BUG_ON(calls != spufs_calls);
|
||||||
|
|
||||||
/* we don't need to rcu this, as we hold a reference to the module */
|
/* we don't need to rcu this, as we hold a reference to the module */
|
||||||
@ -53,82 +56,55 @@ static inline void spufs_calls_put(struct spufs_calls *calls) { }
|
|||||||
|
|
||||||
#endif /* CONFIG_SPU_FS_MODULE */
|
#endif /* CONFIG_SPU_FS_MODULE */
|
||||||
|
|
||||||
|
DEFINE_CLASS(spufs_calls, struct spufs_calls *, spufs_calls_put(_T), spufs_calls_get(), void)
|
||||||
|
|
||||||
SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
|
SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
|
||||||
umode_t, mode, int, neighbor_fd)
|
umode_t, mode, int, neighbor_fd)
|
||||||
{
|
{
|
||||||
long ret;
|
CLASS(spufs_calls, calls)();
|
||||||
struct spufs_calls *calls;
|
|
||||||
|
|
||||||
calls = spufs_calls_get();
|
|
||||||
if (!calls)
|
if (!calls)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
if (flags & SPU_CREATE_AFFINITY_SPU) {
|
if (flags & SPU_CREATE_AFFINITY_SPU) {
|
||||||
struct fd neighbor = fdget(neighbor_fd);
|
CLASS(fd, neighbor)(neighbor_fd);
|
||||||
ret = -EBADF;
|
if (fd_empty(neighbor))
|
||||||
if (fd_file(neighbor)) {
|
return -EBADF;
|
||||||
ret = calls->create_thread(name, flags, mode, fd_file(neighbor));
|
return calls->create_thread(name, flags, mode, fd_file(neighbor));
|
||||||
fdput(neighbor);
|
} else {
|
||||||
}
|
return calls->create_thread(name, flags, mode, NULL);
|
||||||
} else
|
}
|
||||||
ret = calls->create_thread(name, flags, mode, NULL);
|
|
||||||
|
|
||||||
spufs_calls_put(calls);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)
|
SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus)
|
||||||
{
|
{
|
||||||
long ret;
|
CLASS(spufs_calls, calls)();
|
||||||
struct fd arg;
|
|
||||||
struct spufs_calls *calls;
|
|
||||||
|
|
||||||
calls = spufs_calls_get();
|
|
||||||
if (!calls)
|
if (!calls)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
||||||
ret = -EBADF;
|
CLASS(fd, arg)(fd);
|
||||||
arg = fdget(fd);
|
if (fd_empty(arg))
|
||||||
if (fd_file(arg)) {
|
return -EBADF;
|
||||||
ret = calls->spu_run(fd_file(arg), unpc, ustatus);
|
|
||||||
fdput(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
spufs_calls_put(calls);
|
return calls->spu_run(fd_file(arg), unpc, ustatus);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COREDUMP
|
#ifdef CONFIG_COREDUMP
|
||||||
int elf_coredump_extra_notes_size(void)
|
int elf_coredump_extra_notes_size(void)
|
||||||
{
|
{
|
||||||
struct spufs_calls *calls;
|
CLASS(spufs_calls, calls)();
|
||||||
int ret;
|
|
||||||
|
|
||||||
calls = spufs_calls_get();
|
|
||||||
if (!calls)
|
if (!calls)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = calls->coredump_extra_notes_size();
|
return calls->coredump_extra_notes_size();
|
||||||
|
|
||||||
spufs_calls_put(calls);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
|
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
|
||||||
{
|
{
|
||||||
struct spufs_calls *calls;
|
CLASS(spufs_calls, calls)();
|
||||||
int ret;
|
|
||||||
|
|
||||||
calls = spufs_calls_get();
|
|
||||||
if (!calls)
|
if (!calls)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = calls->coredump_extra_notes_write(cprm);
|
return calls->coredump_extra_notes_write(cprm);
|
||||||
|
|
||||||
spufs_calls_put(calls);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -901,19 +901,15 @@ static struct miscdevice sgx_dev_provision = {
|
|||||||
int sgx_set_attribute(unsigned long *allowed_attributes,
|
int sgx_set_attribute(unsigned long *allowed_attributes,
|
||||||
unsigned int attribute_fd)
|
unsigned int attribute_fd)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(attribute_fd);
|
CLASS(fd, f)(attribute_fd);
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (fd_file(f)->f_op != &sgx_provision_fops) {
|
if (fd_file(f)->f_op != &sgx_provision_fops)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
*allowed_attributes |= SGX_ATTR_PROVISIONKEY;
|
*allowed_attributes |= SGX_ATTR_PROVISIONKEY;
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sgx_set_attribute);
|
EXPORT_SYMBOL_GPL(sgx_set_attribute);
|
||||||
|
@ -533,17 +533,12 @@ static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error)
|
|||||||
|
|
||||||
static int __sev_issue_cmd(int fd, int id, void *data, int *error)
|
static int __sev_issue_cmd(int fd, int id, void *data, int *error)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd, f)(fd);
|
||||||
int ret;
|
|
||||||
|
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = sev_issue_cmd_external_user(fd_file(f), id, data, error);
|
return sev_issue_cmd_external_user(fd_file(f), id, data, error);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sev_issue_cmd(struct kvm *kvm, int id, void *data, int *error)
|
static int sev_issue_cmd(struct kvm *kvm, int id, void *data, int *error)
|
||||||
@ -2076,23 +2071,21 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
|||||||
{
|
{
|
||||||
struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
|
struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
|
||||||
struct kvm_sev_info *src_sev, *cg_cleanup_sev;
|
struct kvm_sev_info *src_sev, *cg_cleanup_sev;
|
||||||
struct fd f = fdget(source_fd);
|
CLASS(fd, f)(source_fd);
|
||||||
struct kvm *source_kvm;
|
struct kvm *source_kvm;
|
||||||
bool charged = false;
|
bool charged = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (!file_is_kvm(fd_file(f))) {
|
if (!file_is_kvm(fd_file(f)))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
source_kvm = fd_file(f)->private_data;
|
source_kvm = fd_file(f)->private_data;
|
||||||
ret = sev_lock_two_vms(kvm, source_kvm);
|
ret = sev_lock_two_vms(kvm, source_kvm);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_fput;
|
return ret;
|
||||||
|
|
||||||
if (kvm->arch.vm_type != source_kvm->arch.vm_type ||
|
if (kvm->arch.vm_type != source_kvm->arch.vm_type ||
|
||||||
sev_guest(kvm) || !sev_guest(source_kvm)) {
|
sev_guest(kvm) || !sev_guest(source_kvm)) {
|
||||||
@ -2139,8 +2132,6 @@ out_dst_cgroup:
|
|||||||
cg_cleanup_sev->misc_cg = NULL;
|
cg_cleanup_sev->misc_cg = NULL;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
sev_unlock_two_vms(kvm, source_kvm);
|
sev_unlock_two_vms(kvm, source_kvm);
|
||||||
out_fput:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2801,23 +2792,21 @@ failed:
|
|||||||
|
|
||||||
int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(source_fd);
|
CLASS(fd, f)(source_fd);
|
||||||
struct kvm *source_kvm;
|
struct kvm *source_kvm;
|
||||||
struct kvm_sev_info *source_sev, *mirror_sev;
|
struct kvm_sev_info *source_sev, *mirror_sev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (!file_is_kvm(fd_file(f))) {
|
if (!file_is_kvm(fd_file(f)))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto e_source_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
source_kvm = fd_file(f)->private_data;
|
source_kvm = fd_file(f)->private_data;
|
||||||
ret = sev_lock_two_vms(kvm, source_kvm);
|
ret = sev_lock_two_vms(kvm, source_kvm);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto e_source_fput;
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mirrors of mirrors should work, but let's not get silly. Also
|
* Mirrors of mirrors should work, but let's not get silly. Also
|
||||||
@ -2860,8 +2849,6 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
|||||||
|
|
||||||
e_unlock:
|
e_unlock:
|
||||||
sev_unlock_two_vms(kvm, source_kvm);
|
sev_unlock_two_vms(kvm, source_kvm);
|
||||||
e_source_fput:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,21 +35,19 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
|
|||||||
int fd,
|
int fd,
|
||||||
int32_t priority)
|
int32_t priority)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct amdgpu_fpriv *fpriv;
|
struct amdgpu_fpriv *fpriv;
|
||||||
struct amdgpu_ctx_mgr *mgr;
|
struct amdgpu_ctx_mgr *mgr;
|
||||||
struct amdgpu_ctx *ctx;
|
struct amdgpu_ctx *ctx;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
r = amdgpu_file_to_fpriv(fd_file(f), &fpriv);
|
r = amdgpu_file_to_fpriv(fd_file(f), &fpriv);
|
||||||
if (r) {
|
if (r)
|
||||||
fdput(f);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
mgr = &fpriv->ctx_mgr;
|
mgr = &fpriv->ctx_mgr;
|
||||||
mutex_lock(&mgr->lock);
|
mutex_lock(&mgr->lock);
|
||||||
@ -57,7 +55,6 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
|
|||||||
amdgpu_ctx_priority_override(ctx, priority);
|
amdgpu_ctx_priority_override(ctx, priority);
|
||||||
mutex_unlock(&mgr->lock);
|
mutex_unlock(&mgr->lock);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,31 +63,25 @@ static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev,
|
|||||||
unsigned ctx_id,
|
unsigned ctx_id,
|
||||||
int32_t priority)
|
int32_t priority)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct amdgpu_fpriv *fpriv;
|
struct amdgpu_fpriv *fpriv;
|
||||||
struct amdgpu_ctx *ctx;
|
struct amdgpu_ctx *ctx;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
r = amdgpu_file_to_fpriv(fd_file(f), &fpriv);
|
r = amdgpu_file_to_fpriv(fd_file(f), &fpriv);
|
||||||
if (r) {
|
if (r)
|
||||||
fdput(f);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
ctx = amdgpu_ctx_get(fpriv, ctx_id);
|
ctx = amdgpu_ctx_get(fpriv, ctx_id);
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
amdgpu_ctx_priority_override(ctx, priority);
|
amdgpu_ctx_priority_override(ctx, priority);
|
||||||
amdgpu_ctx_put(ctx);
|
amdgpu_ctx_put(ctx);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,16 +712,14 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
|
|||||||
int fd, u32 *handle)
|
int fd, u32 *handle)
|
||||||
{
|
{
|
||||||
struct drm_syncobj *syncobj;
|
struct drm_syncobj *syncobj;
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (fd_file(f)->f_op != &drm_syncobj_file_fops) {
|
if (fd_file(f)->f_op != &drm_syncobj_file_fops)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
/* take a reference to put in the idr */
|
/* take a reference to put in the idr */
|
||||||
syncobj = fd_file(f)->private_data;
|
syncobj = fd_file(f)->private_data;
|
||||||
@ -739,7 +737,6 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
|
|||||||
} else
|
} else
|
||||||
drm_syncobj_put(syncobj);
|
drm_syncobj_put(syncobj);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1615,7 +1615,6 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
|||||||
struct ucma_event *uevent, *tmp;
|
struct ucma_event *uevent, *tmp;
|
||||||
struct ucma_context *ctx;
|
struct ucma_context *ctx;
|
||||||
LIST_HEAD(event_list);
|
LIST_HEAD(event_list);
|
||||||
struct fd f;
|
|
||||||
struct ucma_file *cur_file;
|
struct ucma_file *cur_file;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -1623,21 +1622,17 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Get current fd to protect against it being closed */
|
/* Get current fd to protect against it being closed */
|
||||||
f = fdget(cmd.fd);
|
CLASS(fd, f)(cmd.fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (fd_file(f)->f_op != &ucma_fops) {
|
if (fd_file(f)->f_op != &ucma_fops)
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto file_put;
|
|
||||||
}
|
|
||||||
cur_file = fd_file(f)->private_data;
|
cur_file = fd_file(f)->private_data;
|
||||||
|
|
||||||
/* Validate current fd and prevent destruction of id. */
|
/* Validate current fd and prevent destruction of id. */
|
||||||
ctx = ucma_get_ctx(cur_file, cmd.id);
|
ctx = ucma_get_ctx(cur_file, cmd.id);
|
||||||
if (IS_ERR(ctx)) {
|
if (IS_ERR(ctx))
|
||||||
ret = PTR_ERR(ctx);
|
return PTR_ERR(ctx);
|
||||||
goto file_put;
|
|
||||||
}
|
|
||||||
|
|
||||||
rdma_lock_handler(ctx->cm_id);
|
rdma_lock_handler(ctx->cm_id);
|
||||||
/*
|
/*
|
||||||
@ -1678,8 +1673,6 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
|||||||
err_unlock:
|
err_unlock:
|
||||||
rdma_unlock_handler(ctx->cm_id);
|
rdma_unlock_handler(ctx->cm_id);
|
||||||
ucma_put_ctx(ctx);
|
ucma_put_ctx(ctx);
|
||||||
file_put:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +584,7 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
|
|||||||
if (cmd.fd != -1) {
|
if (cmd.fd != -1) {
|
||||||
/* search for file descriptor */
|
/* search for file descriptor */
|
||||||
f = fdget(cmd.fd);
|
f = fdget(cmd.fd);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto err_tree_mutex_unlock;
|
goto err_tree_mutex_unlock;
|
||||||
}
|
}
|
||||||
@ -632,8 +632,7 @@ static int ib_uverbs_open_xrcd(struct uverbs_attr_bundle *attrs)
|
|||||||
atomic_inc(&xrcd->usecnt);
|
atomic_inc(&xrcd->usecnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd_file(f))
|
fdput(f);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
mutex_unlock(&ibudev->xrcd_tree_mutex);
|
mutex_unlock(&ibudev->xrcd_tree_mutex);
|
||||||
uobj_finalize_uobj_create(&obj->uobject, attrs);
|
uobj_finalize_uobj_create(&obj->uobject, attrs);
|
||||||
@ -648,8 +647,7 @@ err:
|
|||||||
uobj_alloc_abort(&obj->uobject, attrs);
|
uobj_alloc_abort(&obj->uobject, attrs);
|
||||||
|
|
||||||
err_tree_mutex_unlock:
|
err_tree_mutex_unlock:
|
||||||
if (fd_file(f))
|
fdput(f);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
mutex_unlock(&ibudev->xrcd_tree_mutex);
|
mutex_unlock(&ibudev->xrcd_tree_mutex);
|
||||||
|
|
||||||
|
@ -246,22 +246,21 @@ static const struct file_operations request_fops = {
|
|||||||
struct media_request *
|
struct media_request *
|
||||||
media_request_get_by_fd(struct media_device *mdev, int request_fd)
|
media_request_get_by_fd(struct media_device *mdev, int request_fd)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
struct media_request *req;
|
struct media_request *req;
|
||||||
|
|
||||||
if (!mdev || !mdev->ops ||
|
if (!mdev || !mdev->ops ||
|
||||||
!mdev->ops->req_validate || !mdev->ops->req_queue)
|
!mdev->ops->req_validate || !mdev->ops->req_queue)
|
||||||
return ERR_PTR(-EBADR);
|
return ERR_PTR(-EBADR);
|
||||||
|
|
||||||
f = fdget(request_fd);
|
CLASS(fd, f)(request_fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
goto err_no_req_fd;
|
goto err;
|
||||||
|
|
||||||
if (fd_file(f)->f_op != &request_fops)
|
if (fd_file(f)->f_op != &request_fops)
|
||||||
goto err_fput;
|
goto err;
|
||||||
req = fd_file(f)->private_data;
|
req = fd_file(f)->private_data;
|
||||||
if (req->mdev != mdev)
|
if (req->mdev != mdev)
|
||||||
goto err_fput;
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: as long as someone has an open filehandle of the request,
|
* Note: as long as someone has an open filehandle of the request,
|
||||||
@ -272,14 +271,9 @@ media_request_get_by_fd(struct media_device *mdev, int request_fd)
|
|||||||
* before media_request_get() is called.
|
* before media_request_get() is called.
|
||||||
*/
|
*/
|
||||||
media_request_get(req);
|
media_request_get(req);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
|
|
||||||
err_fput:
|
err:
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
err_no_req_fd:
|
|
||||||
dev_dbg(mdev->dev, "cannot find request_fd %d\n", request_fd);
|
dev_dbg(mdev->dev, "cannot find request_fd %d\n", request_fd);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
@ -815,28 +815,23 @@ void __exit lirc_dev_exit(void)
|
|||||||
|
|
||||||
struct rc_dev *rc_dev_get_from_fd(int fd, bool write)
|
struct rc_dev *rc_dev_get_from_fd(int fd, bool write)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct lirc_fh *fh;
|
struct lirc_fh *fh;
|
||||||
struct rc_dev *dev;
|
struct rc_dev *dev;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
if (fd_file(f)->f_op != &lirc_fops) {
|
if (fd_file(f)->f_op != &lirc_fops)
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
|
||||||
|
|
||||||
if (write && !(fd_file(f)->f_mode & FMODE_WRITE)) {
|
if (write && !(fd_file(f)->f_mode & FMODE_WRITE))
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-EPERM);
|
return ERR_PTR(-EPERM);
|
||||||
}
|
|
||||||
|
|
||||||
fh = fd_file(f)->private_data;
|
fh = fd_file(f)->private_data;
|
||||||
dev = fh->rc;
|
dev = fh->rc;
|
||||||
|
|
||||||
get_device(&dev->dev);
|
get_device(&dev->dev);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -104,15 +104,14 @@ static int vfio_group_ioctl_set_container(struct vfio_group *group,
|
|||||||
{
|
{
|
||||||
struct vfio_container *container;
|
struct vfio_container *container;
|
||||||
struct iommufd_ctx *iommufd;
|
struct iommufd_ctx *iommufd;
|
||||||
struct fd f;
|
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (get_user(fd, arg))
|
if (get_user(fd, arg))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
mutex_lock(&group->group_lock);
|
mutex_lock(&group->group_lock);
|
||||||
@ -153,7 +152,6 @@ static int vfio_group_ioctl_set_container(struct vfio_group *group,
|
|||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
mutex_unlock(&group->group_lock);
|
mutex_unlock(&group->group_lock);
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,6 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
void (*thread)(void *, void *),
|
void (*thread)(void *, void *),
|
||||||
void *data, struct virqfd **pvirqfd, int fd)
|
void *data, struct virqfd **pvirqfd, int fd)
|
||||||
{
|
{
|
||||||
struct fd irqfd;
|
|
||||||
struct eventfd_ctx *ctx;
|
struct eventfd_ctx *ctx;
|
||||||
struct virqfd *virqfd;
|
struct virqfd *virqfd;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -133,8 +132,8 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
INIT_WORK(&virqfd->inject, virqfd_inject);
|
INIT_WORK(&virqfd->inject, virqfd_inject);
|
||||||
INIT_WORK(&virqfd->flush_inject, virqfd_flush_inject);
|
INIT_WORK(&virqfd->flush_inject, virqfd_flush_inject);
|
||||||
|
|
||||||
irqfd = fdget(fd);
|
CLASS(fd, irqfd)(fd);
|
||||||
if (!fd_file(irqfd)) {
|
if (fd_empty(irqfd)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto err_fd;
|
goto err_fd;
|
||||||
}
|
}
|
||||||
@ -142,7 +141,7 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
ctx = eventfd_ctx_fileget(fd_file(irqfd));
|
ctx = eventfd_ctx_fileget(fd_file(irqfd));
|
||||||
if (IS_ERR(ctx)) {
|
if (IS_ERR(ctx)) {
|
||||||
ret = PTR_ERR(ctx);
|
ret = PTR_ERR(ctx);
|
||||||
goto err_ctx;
|
goto err_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
virqfd->eventfd = ctx;
|
virqfd->eventfd = ctx;
|
||||||
@ -181,18 +180,9 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
if ((!handler || handler(opaque, data)) && thread)
|
if ((!handler || handler(opaque, data)) && thread)
|
||||||
schedule_work(&virqfd->inject);
|
schedule_work(&virqfd->inject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not drop the file until the irqfd is fully initialized,
|
|
||||||
* otherwise we might race against the EPOLLHUP.
|
|
||||||
*/
|
|
||||||
fdput(irqfd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_busy:
|
err_busy:
|
||||||
eventfd_ctx_put(ctx);
|
eventfd_ctx_put(ctx);
|
||||||
err_ctx:
|
|
||||||
fdput(irqfd);
|
|
||||||
err_fd:
|
err_fd:
|
||||||
kfree(virqfd);
|
kfree(virqfd);
|
||||||
|
|
||||||
|
@ -112,7 +112,6 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
|
|||||||
struct eventfd_ctx *eventfd = NULL;
|
struct eventfd_ctx *eventfd = NULL;
|
||||||
struct hsm_irqfd *irqfd, *tmp;
|
struct hsm_irqfd *irqfd, *tmp;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
struct fd f;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
|
irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
|
||||||
@ -124,8 +123,8 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
|
|||||||
INIT_LIST_HEAD(&irqfd->list);
|
INIT_LIST_HEAD(&irqfd->list);
|
||||||
INIT_WORK(&irqfd->shutdown, hsm_irqfd_shutdown_work);
|
INIT_WORK(&irqfd->shutdown, hsm_irqfd_shutdown_work);
|
||||||
|
|
||||||
f = fdget(args->fd);
|
CLASS(fd, f)(args->fd);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -133,7 +132,7 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
|
|||||||
eventfd = eventfd_ctx_fileget(fd_file(f));
|
eventfd = eventfd_ctx_fileget(fd_file(f));
|
||||||
if (IS_ERR(eventfd)) {
|
if (IS_ERR(eventfd)) {
|
||||||
ret = PTR_ERR(eventfd);
|
ret = PTR_ERR(eventfd);
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
irqfd->eventfd = eventfd;
|
irqfd->eventfd = eventfd;
|
||||||
@ -162,13 +161,9 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
|
|||||||
if (events & EPOLLIN)
|
if (events & EPOLLIN)
|
||||||
acrn_irqfd_inject(irqfd);
|
acrn_irqfd_inject(irqfd);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
if (eventfd && !IS_ERR(eventfd))
|
eventfd_ctx_put(eventfd);
|
||||||
eventfd_ctx_put(eventfd);
|
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
out:
|
out:
|
||||||
kfree(irqfd);
|
kfree(irqfd);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -965,10 +965,11 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
struct fd f;
|
|
||||||
void *dm_op;
|
void *dm_op;
|
||||||
int ret, idx;
|
int ret, idx;
|
||||||
|
|
||||||
|
CLASS(fd, f)(irqfd->fd);
|
||||||
|
|
||||||
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
||||||
if (!kirqfd)
|
if (!kirqfd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -984,8 +985,7 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
kirqfd->dom = irqfd->dom;
|
kirqfd->dom = irqfd->dom;
|
||||||
INIT_WORK(&kirqfd->shutdown, irqfd_shutdown);
|
INIT_WORK(&kirqfd->shutdown, irqfd_shutdown);
|
||||||
|
|
||||||
f = fdget(irqfd->fd);
|
if (fd_empty(f)) {
|
||||||
if (!fd_file(f)) {
|
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto error_kfree;
|
goto error_kfree;
|
||||||
}
|
}
|
||||||
@ -993,7 +993,7 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
kirqfd->eventfd = eventfd_ctx_fileget(fd_file(f));
|
kirqfd->eventfd = eventfd_ctx_fileget(fd_file(f));
|
||||||
if (IS_ERR(kirqfd->eventfd)) {
|
if (IS_ERR(kirqfd->eventfd)) {
|
||||||
ret = PTR_ERR(kirqfd->eventfd);
|
ret = PTR_ERR(kirqfd->eventfd);
|
||||||
goto error_fd_put;
|
goto error_kfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1026,20 +1026,11 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
irqfd_inject(kirqfd);
|
irqfd_inject(kirqfd);
|
||||||
|
|
||||||
srcu_read_unlock(&irqfds_srcu, idx);
|
srcu_read_unlock(&irqfds_srcu, idx);
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not drop the file until the kirqfd is fully initialized, otherwise
|
|
||||||
* we might race against the EPOLLHUP.
|
|
||||||
*/
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_eventfd:
|
error_eventfd:
|
||||||
eventfd_ctx_put(kirqfd->eventfd);
|
eventfd_ctx_put(kirqfd->eventfd);
|
||||||
|
|
||||||
error_fd_put:
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
error_kfree:
|
error_kfree:
|
||||||
kfree(kirqfd);
|
kfree(kirqfd);
|
||||||
return ret;
|
return ret;
|
||||||
@ -1350,7 +1341,6 @@ static int privcmd_ioeventfd_assign(struct privcmd_ioeventfd *ioeventfd)
|
|||||||
struct privcmd_kernel_ioeventfd *kioeventfd;
|
struct privcmd_kernel_ioeventfd *kioeventfd;
|
||||||
struct privcmd_kernel_ioreq *kioreq;
|
struct privcmd_kernel_ioreq *kioreq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct fd f;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Check for range overflow */
|
/* Check for range overflow */
|
||||||
@ -1370,15 +1360,7 @@ static int privcmd_ioeventfd_assign(struct privcmd_ioeventfd *ioeventfd)
|
|||||||
if (!kioeventfd)
|
if (!kioeventfd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
f = fdget(ioeventfd->event_fd);
|
kioeventfd->eventfd = eventfd_ctx_fdget(ioeventfd->event_fd);
|
||||||
if (!fd_file(f)) {
|
|
||||||
ret = -EBADF;
|
|
||||||
goto error_kfree;
|
|
||||||
}
|
|
||||||
|
|
||||||
kioeventfd->eventfd = eventfd_ctx_fileget(fd_file(f));
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
if (IS_ERR(kioeventfd->eventfd)) {
|
if (IS_ERR(kioeventfd->eventfd)) {
|
||||||
ret = PTR_ERR(kioeventfd->eventfd);
|
ret = PTR_ERR(kioeventfd->eventfd);
|
||||||
goto error_kfree;
|
goto error_kfree;
|
||||||
|
@ -1308,9 +1308,9 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
|
|||||||
ret = btrfs_mksubvol(&file->f_path, idmap, name,
|
ret = btrfs_mksubvol(&file->f_path, idmap, name,
|
||||||
namelen, NULL, readonly, inherit);
|
namelen, NULL, readonly, inherit);
|
||||||
} else {
|
} else {
|
||||||
struct fd src = fdget(fd);
|
CLASS(fd, src)(fd);
|
||||||
struct inode *src_inode;
|
struct inode *src_inode;
|
||||||
if (!fd_file(src)) {
|
if (fd_empty(src)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_drop_write;
|
goto out_drop_write;
|
||||||
}
|
}
|
||||||
@ -1341,7 +1341,6 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
|
|||||||
BTRFS_I(src_inode)->root,
|
BTRFS_I(src_inode)->root,
|
||||||
readonly, inherit);
|
readonly, inherit);
|
||||||
}
|
}
|
||||||
fdput(src);
|
|
||||||
}
|
}
|
||||||
out_drop_write:
|
out_drop_write:
|
||||||
mnt_drop_write_file(file);
|
mnt_drop_write_file(file);
|
||||||
|
@ -347,13 +347,10 @@ EXPORT_SYMBOL_GPL(eventfd_fget);
|
|||||||
*/
|
*/
|
||||||
struct eventfd_ctx *eventfd_ctx_fdget(int fd)
|
struct eventfd_ctx *eventfd_ctx_fdget(int fd)
|
||||||
{
|
{
|
||||||
struct eventfd_ctx *ctx;
|
CLASS(fd, f)(fd);
|
||||||
struct fd f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
ctx = eventfd_ctx_fileget(fd_file(f));
|
return eventfd_ctx_fileget(fd_file(f));
|
||||||
fdput(f);
|
|
||||||
return ctx;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(eventfd_ctx_fdget);
|
EXPORT_SYMBOL_GPL(eventfd_ctx_fdget);
|
||||||
|
|
||||||
|
@ -2259,25 +2259,22 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
int full_check = 0;
|
int full_check = 0;
|
||||||
struct fd f, tf;
|
|
||||||
struct eventpoll *ep;
|
struct eventpoll *ep;
|
||||||
struct epitem *epi;
|
struct epitem *epi;
|
||||||
struct eventpoll *tep = NULL;
|
struct eventpoll *tep = NULL;
|
||||||
|
|
||||||
error = -EBADF;
|
CLASS(fd, f)(epfd);
|
||||||
f = fdget(epfd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
return -EBADF;
|
||||||
goto error_return;
|
|
||||||
|
|
||||||
/* Get the "struct file *" for the target file */
|
/* Get the "struct file *" for the target file */
|
||||||
tf = fdget(fd);
|
CLASS(fd, tf)(fd);
|
||||||
if (!fd_file(tf))
|
if (fd_empty(tf))
|
||||||
goto error_fput;
|
return -EBADF;
|
||||||
|
|
||||||
/* The target file descriptor must support poll */
|
/* The target file descriptor must support poll */
|
||||||
error = -EPERM;
|
|
||||||
if (!file_can_poll(fd_file(tf)))
|
if (!file_can_poll(fd_file(tf)))
|
||||||
goto error_tgt_fput;
|
return -EPERM;
|
||||||
|
|
||||||
/* Check if EPOLLWAKEUP is allowed */
|
/* Check if EPOLLWAKEUP is allowed */
|
||||||
if (ep_op_has_event(op))
|
if (ep_op_has_event(op))
|
||||||
@ -2396,12 +2393,6 @@ error_tgt_fput:
|
|||||||
loop_check_gen++;
|
loop_check_gen++;
|
||||||
mutex_unlock(&epnested_mutex);
|
mutex_unlock(&epnested_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
fdput(tf);
|
|
||||||
error_fput:
|
|
||||||
fdput(f);
|
|
||||||
error_return:
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2429,8 +2420,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
|||||||
static int do_epoll_wait(int epfd, struct epoll_event __user *events,
|
static int do_epoll_wait(int epfd, struct epoll_event __user *events,
|
||||||
int maxevents, struct timespec64 *to)
|
int maxevents, struct timespec64 *to)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
struct fd f;
|
|
||||||
struct eventpoll *ep;
|
struct eventpoll *ep;
|
||||||
|
|
||||||
/* The maximum number of event must be greater than zero */
|
/* The maximum number of event must be greater than zero */
|
||||||
@ -2442,17 +2431,16 @@ static int do_epoll_wait(int epfd, struct epoll_event __user *events,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Get the "struct file *" for the eventpoll file */
|
/* Get the "struct file *" for the eventpoll file */
|
||||||
f = fdget(epfd);
|
CLASS(fd, f)(epfd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to check that the file structure underneath the fd
|
* We have to check that the file structure underneath the fd
|
||||||
* the user passed to us _is_ an eventpoll file.
|
* the user passed to us _is_ an eventpoll file.
|
||||||
*/
|
*/
|
||||||
error = -EINVAL;
|
|
||||||
if (!is_file_epoll(fd_file(f)))
|
if (!is_file_epoll(fd_file(f)))
|
||||||
goto error_fput;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point it is safe to assume that the "private_data" contains
|
* At this point it is safe to assume that the "private_data" contains
|
||||||
@ -2461,11 +2449,7 @@ static int do_epoll_wait(int epfd, struct epoll_event __user *events,
|
|||||||
ep = fd_file(f)->private_data;
|
ep = fd_file(f)->private_data;
|
||||||
|
|
||||||
/* Time to fish for events ... */
|
/* Time to fish for events ... */
|
||||||
error = ep_poll(ep, events, maxevents, to);
|
return ep_poll(ep, events, maxevents, to);
|
||||||
|
|
||||||
error_fput:
|
|
||||||
fdput(f);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events,
|
SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events,
|
||||||
|
@ -1330,7 +1330,6 @@ group_extend_out:
|
|||||||
|
|
||||||
case EXT4_IOC_MOVE_EXT: {
|
case EXT4_IOC_MOVE_EXT: {
|
||||||
struct move_extent me;
|
struct move_extent me;
|
||||||
struct fd donor;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(filp->f_mode & FMODE_READ) ||
|
if (!(filp->f_mode & FMODE_READ) ||
|
||||||
@ -1342,30 +1341,26 @@ group_extend_out:
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
me.moved_len = 0;
|
me.moved_len = 0;
|
||||||
|
|
||||||
donor = fdget(me.donor_fd);
|
CLASS(fd, donor)(me.donor_fd);
|
||||||
if (!fd_file(donor))
|
if (fd_empty(donor))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (!(fd_file(donor)->f_mode & FMODE_WRITE)) {
|
if (!(fd_file(donor)->f_mode & FMODE_WRITE))
|
||||||
err = -EBADF;
|
return -EBADF;
|
||||||
goto mext_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ext4_has_feature_bigalloc(sb)) {
|
if (ext4_has_feature_bigalloc(sb)) {
|
||||||
ext4_msg(sb, KERN_ERR,
|
ext4_msg(sb, KERN_ERR,
|
||||||
"Online defrag not supported with bigalloc");
|
"Online defrag not supported with bigalloc");
|
||||||
err = -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
goto mext_out;
|
|
||||||
} else if (IS_DAX(inode)) {
|
} else if (IS_DAX(inode)) {
|
||||||
ext4_msg(sb, KERN_ERR,
|
ext4_msg(sb, KERN_ERR,
|
||||||
"Online defrag not supported with DAX");
|
"Online defrag not supported with DAX");
|
||||||
err = -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
goto mext_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mnt_want_write_file(filp);
|
err = mnt_want_write_file(filp);
|
||||||
if (err)
|
if (err)
|
||||||
goto mext_out;
|
return err;
|
||||||
|
|
||||||
err = ext4_move_extents(filp, fd_file(donor), me.orig_start,
|
err = ext4_move_extents(filp, fd_file(donor), me.orig_start,
|
||||||
me.donor_start, me.len, &me.moved_len);
|
me.donor_start, me.len, &me.moved_len);
|
||||||
@ -1374,8 +1369,6 @@ group_extend_out:
|
|||||||
if (copy_to_user((struct move_extent __user *)arg,
|
if (copy_to_user((struct move_extent __user *)arg,
|
||||||
&me, sizeof(me)))
|
&me, sizeof(me)))
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
mext_out:
|
|
||||||
fdput(donor);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3038,32 +3038,27 @@ out:
|
|||||||
static int __f2fs_ioc_move_range(struct file *filp,
|
static int __f2fs_ioc_move_range(struct file *filp,
|
||||||
struct f2fs_move_range *range)
|
struct f2fs_move_range *range)
|
||||||
{
|
{
|
||||||
struct fd dst;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(filp->f_mode & FMODE_READ) ||
|
if (!(filp->f_mode & FMODE_READ) ||
|
||||||
!(filp->f_mode & FMODE_WRITE))
|
!(filp->f_mode & FMODE_WRITE))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
dst = fdget(range->dst_fd);
|
CLASS(fd, dst)(range->dst_fd);
|
||||||
if (!fd_file(dst))
|
if (fd_empty(dst))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (!(fd_file(dst)->f_mode & FMODE_WRITE)) {
|
if (!(fd_file(dst)->f_mode & FMODE_WRITE))
|
||||||
err = -EBADF;
|
return -EBADF;
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mnt_want_write_file(filp);
|
err = mnt_want_write_file(filp);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out;
|
return err;
|
||||||
|
|
||||||
err = f2fs_move_file_range(filp, range->pos_in, fd_file(dst),
|
err = f2fs_move_file_range(filp, range->pos_in, fd_file(dst),
|
||||||
range->pos_out, range->len);
|
range->pos_out, range->len);
|
||||||
|
|
||||||
mnt_drop_write_file(filp);
|
mnt_drop_write_file(filp);
|
||||||
err_out:
|
|
||||||
fdput(dst);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
fs/fcntl.c
42
fs/fcntl.c
@ -572,24 +572,21 @@ static int check_fcntl_cmd(unsigned cmd)
|
|||||||
|
|
||||||
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
|
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_raw(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
long err = -EBADF;
|
long err;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
|
if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
|
||||||
if (!check_fcntl_cmd(cmd))
|
if (!check_fcntl_cmd(cmd))
|
||||||
goto out1;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = security_file_fcntl(fd_file(f), cmd, arg);
|
err = security_file_fcntl(fd_file(f), cmd, arg);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = do_fcntl(fd, cmd, arg, fd_file(f));
|
err = do_fcntl(fd, cmd, arg, fd_file(f));
|
||||||
|
|
||||||
out1:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,21 +595,21 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
|
|||||||
unsigned long, arg)
|
unsigned long, arg)
|
||||||
{
|
{
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
struct fd f = fdget_raw(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
struct flock64 flock;
|
struct flock64 flock;
|
||||||
long err = -EBADF;
|
long err;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
|
if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
|
||||||
if (!check_fcntl_cmd(cmd))
|
if (!check_fcntl_cmd(cmd))
|
||||||
goto out1;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = security_file_fcntl(fd_file(f), cmd, arg);
|
err = security_file_fcntl(fd_file(f), cmd, arg);
|
||||||
if (err)
|
if (err)
|
||||||
goto out1;
|
return err;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_GETLK64:
|
case F_GETLK64:
|
||||||
@ -637,9 +634,6 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
|
|||||||
err = do_fcntl(fd, cmd, arg, fd_file(f));
|
err = do_fcntl(fd, cmd, arg, fd_file(f));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out1:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -735,21 +729,21 @@ static int fixup_compat_flock(struct flock *flock)
|
|||||||
static long do_compat_fcntl64(unsigned int fd, unsigned int cmd,
|
static long do_compat_fcntl64(unsigned int fd, unsigned int cmd,
|
||||||
compat_ulong_t arg)
|
compat_ulong_t arg)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_raw(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
struct flock flock;
|
struct flock flock;
|
||||||
long err = -EBADF;
|
long err;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return err;
|
return -EBADF;
|
||||||
|
|
||||||
if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
|
if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
|
||||||
if (!check_fcntl_cmd(cmd))
|
if (!check_fcntl_cmd(cmd))
|
||||||
goto out_put;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = security_file_fcntl(fd_file(f), cmd, arg);
|
err = security_file_fcntl(fd_file(f), cmd, arg);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put;
|
return err;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_GETLK:
|
case F_GETLK:
|
||||||
@ -792,8 +786,6 @@ static long do_compat_fcntl64(unsigned int fd, unsigned int cmd,
|
|||||||
err = do_fcntl(fd, cmd, arg, fd_file(f));
|
err = do_fcntl(fd, cmd, arg, fd_file(f));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out_put:
|
|
||||||
fdput(f);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,12 +139,11 @@ static int get_path_from_fd(int fd, struct path *root)
|
|||||||
path_get(root);
|
path_get(root);
|
||||||
spin_unlock(&fs->lock);
|
spin_unlock(&fs->lock);
|
||||||
} else {
|
} else {
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
*root = fd_file(f)->f_path;
|
*root = fd_file(f)->f_path;
|
||||||
path_get(root);
|
path_get(root);
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
19
fs/fsopen.c
19
fs/fsopen.c
@ -349,7 +349,6 @@ SYSCALL_DEFINE5(fsconfig,
|
|||||||
int, aux)
|
int, aux)
|
||||||
{
|
{
|
||||||
struct fs_context *fc;
|
struct fs_context *fc;
|
||||||
struct fd f;
|
|
||||||
int ret;
|
int ret;
|
||||||
int lookup_flags = 0;
|
int lookup_flags = 0;
|
||||||
|
|
||||||
@ -392,12 +391,11 @@ SYSCALL_DEFINE5(fsconfig,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
ret = -EINVAL;
|
|
||||||
if (fd_file(f)->f_op != &fscontext_fops)
|
if (fd_file(f)->f_op != &fscontext_fops)
|
||||||
goto out_f;
|
return -EINVAL;
|
||||||
|
|
||||||
fc = fd_file(f)->private_data;
|
fc = fd_file(f)->private_data;
|
||||||
if (fc->ops == &legacy_fs_context_ops) {
|
if (fc->ops == &legacy_fs_context_ops) {
|
||||||
@ -407,17 +405,14 @@ SYSCALL_DEFINE5(fsconfig,
|
|||||||
case FSCONFIG_SET_PATH_EMPTY:
|
case FSCONFIG_SET_PATH_EMPTY:
|
||||||
case FSCONFIG_SET_FD:
|
case FSCONFIG_SET_FD:
|
||||||
case FSCONFIG_CMD_CREATE_EXCL:
|
case FSCONFIG_CMD_CREATE_EXCL:
|
||||||
ret = -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
goto out_f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_key) {
|
if (_key) {
|
||||||
param.key = strndup_user(_key, 256);
|
param.key = strndup_user(_key, 256);
|
||||||
if (IS_ERR(param.key)) {
|
if (IS_ERR(param.key))
|
||||||
ret = PTR_ERR(param.key);
|
return PTR_ERR(param.key);
|
||||||
goto out_f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
@ -496,7 +491,5 @@ SYSCALL_DEFINE5(fsconfig,
|
|||||||
}
|
}
|
||||||
out_key:
|
out_key:
|
||||||
kfree(param.key);
|
kfree(param.key);
|
||||||
out_f:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2371,13 +2371,12 @@ static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
|
|||||||
int res;
|
int res;
|
||||||
int oldfd;
|
int oldfd;
|
||||||
struct fuse_dev *fud = NULL;
|
struct fuse_dev *fud = NULL;
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
if (get_user(oldfd, argp))
|
if (get_user(oldfd, argp))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
f = fdget(oldfd);
|
CLASS(fd, f)(oldfd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2394,7 +2393,6 @@ static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
|
|||||||
mutex_unlock(&fuse_mutex);
|
mutex_unlock(&fuse_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
fs/ioctl.c
23
fs/ioctl.c
@ -231,11 +231,11 @@ static int ioctl_fiemap(struct file *filp, struct fiemap __user *ufiemap)
|
|||||||
static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
|
static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
|
||||||
u64 off, u64 olen, u64 destoff)
|
u64 off, u64 olen, u64 destoff)
|
||||||
{
|
{
|
||||||
struct fd src_file = fdget(srcfd);
|
CLASS(fd, src_file)(srcfd);
|
||||||
loff_t cloned;
|
loff_t cloned;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!fd_file(src_file))
|
if (fd_empty(src_file))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
cloned = vfs_clone_file_range(fd_file(src_file), off, dst_file, destoff,
|
cloned = vfs_clone_file_range(fd_file(src_file), off, dst_file, destoff,
|
||||||
olen, 0);
|
olen, 0);
|
||||||
@ -245,7 +245,6 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
else
|
else
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fdput(src_file);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,22 +891,20 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
|
|||||||
|
|
||||||
SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
|
SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = security_file_ioctl(fd_file(f), cmd, arg);
|
error = security_file_ioctl(fd_file(f), cmd, arg);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
return error;
|
||||||
|
|
||||||
error = do_vfs_ioctl(fd_file(f), fd, cmd, arg);
|
error = do_vfs_ioctl(fd_file(f), fd, cmd, arg);
|
||||||
if (error == -ENOIOCTLCMD)
|
if (error == -ENOIOCTLCMD)
|
||||||
error = vfs_ioctl(fd_file(f), cmd, arg);
|
error = vfs_ioctl(fd_file(f), cmd, arg);
|
||||||
|
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -950,15 +947,15 @@ EXPORT_SYMBOL(compat_ptr_ioctl);
|
|||||||
COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
|
COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
|
||||||
compat_ulong_t, arg)
|
compat_ulong_t, arg)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = security_file_ioctl_compat(fd_file(f), cmd, arg);
|
error = security_file_ioctl_compat(fd_file(f), cmd, arg);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
return error;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
/* FICLONE takes an int argument, so don't use compat_ptr() */
|
/* FICLONE takes an int argument, so don't use compat_ptr() */
|
||||||
@ -1009,10 +1006,6 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
|
|||||||
error = -ENOTTY;
|
error = -ENOTTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -175,15 +175,11 @@ ssize_t kernel_read_file_from_fd(int fd, loff_t offset, void **buf,
|
|||||||
size_t buf_size, size_t *file_size,
|
size_t buf_size, size_t *file_size,
|
||||||
enum kernel_read_file_id id)
|
enum kernel_read_file_id id)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
ssize_t ret = -EBADF;
|
|
||||||
|
|
||||||
if (!fd_file(f) || !(fd_file(f)->f_mode & FMODE_READ))
|
if (fd_empty(f) || !(fd_file(f)->f_mode & FMODE_READ))
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
ret = kernel_read_file(fd_file(f), offset, buf, buf_size, file_size, id);
|
return kernel_read_file(fd_file(f), offset, buf, buf_size, file_size, id);
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
|
EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
|
||||||
|
15
fs/locks.c
15
fs/locks.c
@ -2136,7 +2136,6 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
|||||||
{
|
{
|
||||||
int can_sleep, error, type;
|
int can_sleep, error, type;
|
||||||
struct file_lock fl;
|
struct file_lock fl;
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LOCK_MAND locks were broken for a long time in that they never
|
* LOCK_MAND locks were broken for a long time in that they never
|
||||||
@ -2155,19 +2154,18 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
|||||||
if (type < 0)
|
if (type < 0)
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
error = -EBADF;
|
CLASS(fd, f)(fd);
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
return -EBADF;
|
||||||
return error;
|
|
||||||
|
|
||||||
if (type != F_UNLCK && !(fd_file(f)->f_mode & (FMODE_READ | FMODE_WRITE)))
|
if (type != F_UNLCK && !(fd_file(f)->f_mode & (FMODE_READ | FMODE_WRITE)))
|
||||||
goto out_putf;
|
return -EBADF;
|
||||||
|
|
||||||
flock_make_lock(fd_file(f), &fl, type);
|
flock_make_lock(fd_file(f), &fl, type);
|
||||||
|
|
||||||
error = security_file_lock(fd_file(f), fl.c.flc_type);
|
error = security_file_lock(fd_file(f), fl.c.flc_type);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_putf;
|
return error;
|
||||||
|
|
||||||
can_sleep = !(cmd & LOCK_NB);
|
can_sleep = !(cmd & LOCK_NB);
|
||||||
if (can_sleep)
|
if (can_sleep)
|
||||||
@ -2181,9 +2179,6 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
|||||||
error = locks_lock_file_wait(fd_file(f), &fl);
|
error = locks_lock_file_wait(fd_file(f), &fl);
|
||||||
|
|
||||||
locks_release_private(&fl);
|
locks_release_private(&fl);
|
||||||
out_putf:
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
fs/namei.c
13
fs/namei.c
@ -2544,26 +2544,22 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Caller must check execute permissions on the starting path component */
|
/* Caller must check execute permissions on the starting path component */
|
||||||
struct fd f = fdget_raw(nd->dfd);
|
CLASS(fd_raw, f)(nd->dfd);
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
if (flags & LOOKUP_LINKAT_EMPTY) {
|
if (flags & LOOKUP_LINKAT_EMPTY) {
|
||||||
if (fd_file(f)->f_cred != current_cred() &&
|
if (fd_file(f)->f_cred != current_cred() &&
|
||||||
!ns_capable(fd_file(f)->f_cred->user_ns, CAP_DAC_READ_SEARCH)) {
|
!ns_capable(fd_file(f)->f_cred->user_ns, CAP_DAC_READ_SEARCH))
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dentry = fd_file(f)->f_path.dentry;
|
dentry = fd_file(f)->f_path.dentry;
|
||||||
|
|
||||||
if (*s && unlikely(!d_can_lookup(dentry))) {
|
if (*s && unlikely(!d_can_lookup(dentry)))
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-ENOTDIR);
|
return ERR_PTR(-ENOTDIR);
|
||||||
}
|
|
||||||
|
|
||||||
nd->path = fd_file(f)->f_path;
|
nd->path = fd_file(f)->f_path;
|
||||||
if (flags & LOOKUP_RCU) {
|
if (flags & LOOKUP_RCU) {
|
||||||
@ -2573,7 +2569,6 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
|
|||||||
path_get(&nd->path);
|
path_get(&nd->path);
|
||||||
nd->inode = nd->path.dentry->d_inode;
|
nd->inode = nd->path.dentry->d_inode;
|
||||||
}
|
}
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For scoped-lookups we need to set the root to the dirfd as well. */
|
/* For scoped-lookups we need to set the root to the dirfd as well. */
|
||||||
|
@ -4107,7 +4107,6 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
|
|||||||
struct file *file;
|
struct file *file;
|
||||||
struct path newmount;
|
struct path newmount;
|
||||||
struct mount *mnt;
|
struct mount *mnt;
|
||||||
struct fd f;
|
|
||||||
unsigned int mnt_flags = 0;
|
unsigned int mnt_flags = 0;
|
||||||
long ret;
|
long ret;
|
||||||
|
|
||||||
@ -4135,19 +4134,18 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fdget(fs_fd);
|
CLASS(fd, f)(fs_fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = -EINVAL;
|
|
||||||
if (fd_file(f)->f_op != &fscontext_fops)
|
if (fd_file(f)->f_op != &fscontext_fops)
|
||||||
goto err_fsfd;
|
return -EINVAL;
|
||||||
|
|
||||||
fc = fd_file(f)->private_data;
|
fc = fd_file(f)->private_data;
|
||||||
|
|
||||||
ret = mutex_lock_interruptible(&fc->uapi_mutex);
|
ret = mutex_lock_interruptible(&fc->uapi_mutex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_fsfd;
|
return ret;
|
||||||
|
|
||||||
/* There must be a valid superblock or we can't mount it */
|
/* There must be a valid superblock or we can't mount it */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@ -4214,8 +4212,6 @@ err_path:
|
|||||||
path_put(&newmount);
|
path_put(&newmount);
|
||||||
err_unlock:
|
err_unlock:
|
||||||
mutex_unlock(&fc->uapi_mutex);
|
mutex_unlock(&fc->uapi_mutex);
|
||||||
err_fsfd:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4670,10 +4666,8 @@ out:
|
|||||||
static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
||||||
struct mount_kattr *kattr, unsigned int flags)
|
struct mount_kattr *kattr, unsigned int flags)
|
||||||
{
|
{
|
||||||
int err = 0;
|
|
||||||
struct ns_common *ns;
|
struct ns_common *ns;
|
||||||
struct user_namespace *mnt_userns;
|
struct user_namespace *mnt_userns;
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
if (!((attr->attr_set | attr->attr_clr) & MOUNT_ATTR_IDMAP))
|
if (!((attr->attr_set | attr->attr_clr) & MOUNT_ATTR_IDMAP))
|
||||||
return 0;
|
return 0;
|
||||||
@ -4689,20 +4683,16 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
|||||||
if (attr->userns_fd > INT_MAX)
|
if (attr->userns_fd > INT_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(attr->userns_fd);
|
CLASS(fd, f)(attr->userns_fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (!proc_ns_file(fd_file(f))) {
|
if (!proc_ns_file(fd_file(f)))
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
ns = get_proc_ns(file_inode(fd_file(f)));
|
ns = get_proc_ns(file_inode(fd_file(f)));
|
||||||
if (ns->ops->type != CLONE_NEWUSER) {
|
if (ns->ops->type != CLONE_NEWUSER)
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The initial idmapping cannot be used to create an idmapped
|
* The initial idmapping cannot be used to create an idmapped
|
||||||
@ -4713,22 +4703,15 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
|||||||
* result.
|
* result.
|
||||||
*/
|
*/
|
||||||
mnt_userns = container_of(ns, struct user_namespace, ns);
|
mnt_userns = container_of(ns, struct user_namespace, ns);
|
||||||
if (mnt_userns == &init_user_ns) {
|
if (mnt_userns == &init_user_ns)
|
||||||
err = -EPERM;
|
return -EPERM;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We're not controlling the target namespace. */
|
/* We're not controlling the target namespace. */
|
||||||
if (!ns_capable(mnt_userns, CAP_SYS_ADMIN)) {
|
if (!ns_capable(mnt_userns, CAP_SYS_ADMIN))
|
||||||
err = -EPERM;
|
return -EPERM;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
kattr->mnt_userns = get_user_ns(mnt_userns);
|
kattr->mnt_userns = get_user_ns(mnt_userns);
|
||||||
|
return 0;
|
||||||
out_fput:
|
|
||||||
fdput(f);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int build_mount_kattr(const struct mount_attr *attr, size_t usize,
|
static int build_mount_kattr(const struct mount_attr *attr, size_t usize,
|
||||||
|
@ -1002,22 +1002,17 @@ static int fanotify_find_path(int dfd, const char __user *filename,
|
|||||||
dfd, filename, flags);
|
dfd, filename, flags);
|
||||||
|
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
struct fd f = fdget(dfd);
|
CLASS(fd, f)(dfd);
|
||||||
|
|
||||||
ret = -EBADF;
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
return -EBADF;
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = -ENOTDIR;
|
|
||||||
if ((flags & FAN_MARK_ONLYDIR) &&
|
if ((flags & FAN_MARK_ONLYDIR) &&
|
||||||
!(S_ISDIR(file_inode(fd_file(f))->i_mode))) {
|
!(S_ISDIR(file_inode(fd_file(f))->i_mode)))
|
||||||
fdput(f);
|
return -ENOTDIR;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*path = fd_file(f)->f_path;
|
*path = fd_file(f)->f_path;
|
||||||
path_get(path);
|
path_get(path);
|
||||||
fdput(f);
|
|
||||||
} else {
|
} else {
|
||||||
unsigned int lookup_flags = 0;
|
unsigned int lookup_flags = 0;
|
||||||
|
|
||||||
@ -1681,7 +1676,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
struct vfsmount *mnt = NULL;
|
struct vfsmount *mnt = NULL;
|
||||||
struct fsnotify_group *group;
|
struct fsnotify_group *group;
|
||||||
struct fd f;
|
|
||||||
struct path path;
|
struct path path;
|
||||||
struct fan_fsid __fsid, *fsid = NULL;
|
struct fan_fsid __fsid, *fsid = NULL;
|
||||||
u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
|
u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
|
||||||
@ -1751,14 +1745,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
umask = FANOTIFY_EVENT_FLAGS;
|
umask = FANOTIFY_EVENT_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fdget(fanotify_fd);
|
CLASS(fd, f)(fanotify_fd);
|
||||||
if (unlikely(!fd_file(f)))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
/* verify that this is indeed an fanotify instance */
|
/* verify that this is indeed an fanotify instance */
|
||||||
ret = -EINVAL;
|
|
||||||
if (unlikely(fd_file(f)->f_op != &fanotify_fops))
|
if (unlikely(fd_file(f)->f_op != &fanotify_fops))
|
||||||
goto fput_and_out;
|
return -EINVAL;
|
||||||
group = fd_file(f)->private_data;
|
group = fd_file(f)->private_data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1766,23 +1759,21 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
* marks. This also includes setting up such marks by a group that
|
* marks. This also includes setting up such marks by a group that
|
||||||
* was initialized by an unprivileged user.
|
* was initialized by an unprivileged user.
|
||||||
*/
|
*/
|
||||||
ret = -EPERM;
|
|
||||||
if ((!capable(CAP_SYS_ADMIN) ||
|
if ((!capable(CAP_SYS_ADMIN) ||
|
||||||
FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
|
FAN_GROUP_FLAG(group, FANOTIFY_UNPRIV)) &&
|
||||||
mark_type != FAN_MARK_INODE)
|
mark_type != FAN_MARK_INODE)
|
||||||
goto fput_and_out;
|
return -EPERM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Permission events require minimum priority FAN_CLASS_CONTENT.
|
* Permission events require minimum priority FAN_CLASS_CONTENT.
|
||||||
*/
|
*/
|
||||||
ret = -EINVAL;
|
|
||||||
if (mask & FANOTIFY_PERM_EVENTS &&
|
if (mask & FANOTIFY_PERM_EVENTS &&
|
||||||
group->priority < FSNOTIFY_PRIO_CONTENT)
|
group->priority < FSNOTIFY_PRIO_CONTENT)
|
||||||
goto fput_and_out;
|
return -EINVAL;
|
||||||
|
|
||||||
if (mask & FAN_FS_ERROR &&
|
if (mask & FAN_FS_ERROR &&
|
||||||
mark_type != FAN_MARK_FILESYSTEM)
|
mark_type != FAN_MARK_FILESYSTEM)
|
||||||
goto fput_and_out;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Evictable is only relevant for inode marks, because only inode object
|
* Evictable is only relevant for inode marks, because only inode object
|
||||||
@ -1790,7 +1781,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
*/
|
*/
|
||||||
if (flags & FAN_MARK_EVICTABLE &&
|
if (flags & FAN_MARK_EVICTABLE &&
|
||||||
mark_type != FAN_MARK_INODE)
|
mark_type != FAN_MARK_INODE)
|
||||||
goto fput_and_out;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Events that do not carry enough information to report
|
* Events that do not carry enough information to report
|
||||||
@ -1802,7 +1793,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
|
fid_mode = FAN_GROUP_FLAG(group, FANOTIFY_FID_BITS);
|
||||||
if (mask & ~(FANOTIFY_FD_EVENTS|FANOTIFY_EVENT_FLAGS) &&
|
if (mask & ~(FANOTIFY_FD_EVENTS|FANOTIFY_EVENT_FLAGS) &&
|
||||||
(!fid_mode || mark_type == FAN_MARK_MOUNT))
|
(!fid_mode || mark_type == FAN_MARK_MOUNT))
|
||||||
goto fput_and_out;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FAN_RENAME uses special info type records to report the old and
|
* FAN_RENAME uses special info type records to report the old and
|
||||||
@ -1810,23 +1801,22 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
* useful and was not implemented.
|
* useful and was not implemented.
|
||||||
*/
|
*/
|
||||||
if (mask & FAN_RENAME && !(fid_mode & FAN_REPORT_NAME))
|
if (mask & FAN_RENAME && !(fid_mode & FAN_REPORT_NAME))
|
||||||
goto fput_and_out;
|
return -EINVAL;
|
||||||
|
|
||||||
if (mark_cmd == FAN_MARK_FLUSH) {
|
if (mark_cmd == FAN_MARK_FLUSH) {
|
||||||
ret = 0;
|
|
||||||
if (mark_type == FAN_MARK_MOUNT)
|
if (mark_type == FAN_MARK_MOUNT)
|
||||||
fsnotify_clear_vfsmount_marks_by_group(group);
|
fsnotify_clear_vfsmount_marks_by_group(group);
|
||||||
else if (mark_type == FAN_MARK_FILESYSTEM)
|
else if (mark_type == FAN_MARK_FILESYSTEM)
|
||||||
fsnotify_clear_sb_marks_by_group(group);
|
fsnotify_clear_sb_marks_by_group(group);
|
||||||
else
|
else
|
||||||
fsnotify_clear_inode_marks_by_group(group);
|
fsnotify_clear_inode_marks_by_group(group);
|
||||||
goto fput_and_out;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fanotify_find_path(dfd, pathname, &path, flags,
|
ret = fanotify_find_path(dfd, pathname, &path, flags,
|
||||||
(mask & ALL_FSNOTIFY_EVENTS), obj_type);
|
(mask & ALL_FSNOTIFY_EVENTS), obj_type);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fput_and_out;
|
return ret;
|
||||||
|
|
||||||
if (mark_cmd == FAN_MARK_ADD) {
|
if (mark_cmd == FAN_MARK_ADD) {
|
||||||
ret = fanotify_events_supported(group, &path, mask, flags);
|
ret = fanotify_events_supported(group, &path, mask, flags);
|
||||||
@ -1905,8 +1895,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
|
|||||||
|
|
||||||
path_put_and_out:
|
path_put_and_out:
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
fput_and_out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +732,6 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
|
|||||||
struct fsnotify_group *group;
|
struct fsnotify_group *group;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct fd f;
|
|
||||||
int ret;
|
int ret;
|
||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
|
|
||||||
@ -752,21 +751,17 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
|
|||||||
if (unlikely(!(mask & ALL_INOTIFY_BITS)))
|
if (unlikely(!(mask & ALL_INOTIFY_BITS)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (unlikely(!fd_file(f)))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
/* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
|
/* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
|
||||||
if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE))) {
|
if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto fput_and_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* verify that this is indeed an inotify instance */
|
/* verify that this is indeed an inotify instance */
|
||||||
if (unlikely(fd_file(f)->f_op != &inotify_fops)) {
|
if (unlikely(fd_file(f)->f_op != &inotify_fops))
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto fput_and_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(mask & IN_DONT_FOLLOW))
|
if (!(mask & IN_DONT_FOLLOW))
|
||||||
flags |= LOOKUP_FOLLOW;
|
flags |= LOOKUP_FOLLOW;
|
||||||
@ -776,7 +771,7 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
|
|||||||
ret = inotify_find_inode(pathname, &path, flags,
|
ret = inotify_find_inode(pathname, &path, flags,
|
||||||
(mask & IN_ALL_EVENTS));
|
(mask & IN_ALL_EVENTS));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fput_and_out;
|
return ret;
|
||||||
|
|
||||||
/* inode held in place by reference to path; group by fget on fd */
|
/* inode held in place by reference to path; group by fget on fd */
|
||||||
inode = path.dentry->d_inode;
|
inode = path.dentry->d_inode;
|
||||||
@ -785,8 +780,6 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
|
|||||||
/* create/update an inode mark */
|
/* create/update an inode mark */
|
||||||
ret = inotify_update_watch(group, inode, mask);
|
ret = inotify_update_watch(group, inode, mask);
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
fput_and_out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,33 +787,26 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
|
|||||||
{
|
{
|
||||||
struct fsnotify_group *group;
|
struct fsnotify_group *group;
|
||||||
struct inotify_inode_mark *i_mark;
|
struct inotify_inode_mark *i_mark;
|
||||||
struct fd f;
|
CLASS(fd, f)(fd);
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (unlikely(!fd_file(f)))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
/* verify that this is indeed an inotify instance */
|
/* verify that this is indeed an inotify instance */
|
||||||
if (unlikely(fd_file(f)->f_op != &inotify_fops))
|
if (unlikely(fd_file(f)->f_op != &inotify_fops))
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
group = fd_file(f)->private_data;
|
group = fd_file(f)->private_data;
|
||||||
|
|
||||||
i_mark = inotify_idr_find(group, wd);
|
i_mark = inotify_idr_find(group, wd);
|
||||||
if (unlikely(!i_mark))
|
if (unlikely(!i_mark))
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
fsnotify_destroy_mark(&i_mark->fsn_mark, group);
|
fsnotify_destroy_mark(&i_mark->fsn_mark, group);
|
||||||
|
|
||||||
/* match ref taken by inotify_idr_find */
|
/* match ref taken by inotify_idr_find */
|
||||||
fsnotify_put_mark(&i_mark->fsn_mark);
|
fsnotify_put_mark(&i_mark->fsn_mark);
|
||||||
|
return 0;
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1765,42 +1765,41 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
|
|||||||
long fd;
|
long fd;
|
||||||
int sectsize;
|
int sectsize;
|
||||||
char *p = (char *)page;
|
char *p = (char *)page;
|
||||||
struct fd f;
|
|
||||||
ssize_t ret = -EINVAL;
|
ssize_t ret = -EINVAL;
|
||||||
int live_threshold;
|
int live_threshold;
|
||||||
|
|
||||||
if (reg->hr_bdev_file)
|
if (reg->hr_bdev_file)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
/* We can't heartbeat without having had our node number
|
/* We can't heartbeat without having had our node number
|
||||||
* configured yet. */
|
* configured yet. */
|
||||||
if (o2nm_this_node() == O2NM_MAX_NODES)
|
if (o2nm_this_node() == O2NM_MAX_NODES)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
fd = simple_strtol(p, &p, 0);
|
fd = simple_strtol(p, &p, 0);
|
||||||
if (!p || (*p && (*p != '\n')))
|
if (!p || (*p && (*p != '\n')))
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
if (fd < 0 || fd >= INT_MAX)
|
if (fd < 0 || fd >= INT_MAX)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (fd_file(f) == NULL)
|
if (fd_empty(f))
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
if (reg->hr_blocks == 0 || reg->hr_start_block == 0 ||
|
if (reg->hr_blocks == 0 || reg->hr_start_block == 0 ||
|
||||||
reg->hr_block_bytes == 0)
|
reg->hr_block_bytes == 0)
|
||||||
goto out2;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!S_ISBLK(fd_file(f)->f_mapping->host->i_mode))
|
if (!S_ISBLK(fd_file(f)->f_mapping->host->i_mode))
|
||||||
goto out2;
|
return -EINVAL;
|
||||||
|
|
||||||
reg->hr_bdev_file = bdev_file_open_by_dev(fd_file(f)->f_mapping->host->i_rdev,
|
reg->hr_bdev_file = bdev_file_open_by_dev(fd_file(f)->f_mapping->host->i_rdev,
|
||||||
BLK_OPEN_WRITE | BLK_OPEN_READ, NULL, NULL);
|
BLK_OPEN_WRITE | BLK_OPEN_READ, NULL, NULL);
|
||||||
if (IS_ERR(reg->hr_bdev_file)) {
|
if (IS_ERR(reg->hr_bdev_file)) {
|
||||||
ret = PTR_ERR(reg->hr_bdev_file);
|
ret = PTR_ERR(reg->hr_bdev_file);
|
||||||
reg->hr_bdev_file = NULL;
|
reg->hr_bdev_file = NULL;
|
||||||
goto out2;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sectsize = bdev_logical_block_size(reg_bdev(reg));
|
sectsize = bdev_logical_block_size(reg_bdev(reg));
|
||||||
@ -1906,9 +1905,6 @@ out3:
|
|||||||
fput(reg->hr_bdev_file);
|
fput(reg->hr_bdev_file);
|
||||||
reg->hr_bdev_file = NULL;
|
reg->hr_bdev_file = NULL;
|
||||||
}
|
}
|
||||||
out2:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
fs/open.c
61
fs/open.c
@ -187,19 +187,13 @@ long do_ftruncate(struct file *file, loff_t length, int small)
|
|||||||
|
|
||||||
long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
|
long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = do_ftruncate(fd_file(f), length, small);
|
return do_ftruncate(fd_file(f), length, small);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length)
|
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length)
|
||||||
@ -349,14 +343,12 @@ EXPORT_SYMBOL_GPL(vfs_fallocate);
|
|||||||
|
|
||||||
int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len)
|
int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int error = -EBADF;
|
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
error = vfs_fallocate(fd_file(f), mode, offset, len);
|
return -EBADF;
|
||||||
fdput(f);
|
|
||||||
}
|
return vfs_fallocate(fd_file(f), mode, offset, len);
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
|
SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
|
||||||
@ -580,23 +572,18 @@ out:
|
|||||||
|
|
||||||
SYSCALL_DEFINE1(fchdir, unsigned int, fd)
|
SYSCALL_DEFINE1(fchdir, unsigned int, fd)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_raw(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = -EBADF;
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
return -EBADF;
|
||||||
goto out;
|
|
||||||
|
|
||||||
error = -ENOTDIR;
|
|
||||||
if (!d_can_lookup(fd_file(f)->f_path.dentry))
|
if (!d_can_lookup(fd_file(f)->f_path.dentry))
|
||||||
goto out_putf;
|
return -ENOTDIR;
|
||||||
|
|
||||||
error = file_permission(fd_file(f), MAY_EXEC | MAY_CHDIR);
|
error = file_permission(fd_file(f), MAY_EXEC | MAY_CHDIR);
|
||||||
if (!error)
|
if (!error)
|
||||||
set_fs_pwd(current->fs, &fd_file(f)->f_path);
|
set_fs_pwd(current->fs, &fd_file(f)->f_path);
|
||||||
out_putf:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,14 +658,12 @@ int vfs_fchmod(struct file *file, umode_t mode)
|
|||||||
|
|
||||||
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
|
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int err = -EBADF;
|
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
err = vfs_fchmod(fd_file(f), mode);
|
return -EBADF;
|
||||||
fdput(f);
|
|
||||||
}
|
return vfs_fchmod(fd_file(f), mode);
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_fchmodat(int dfd, const char __user *filename, umode_t mode,
|
static int do_fchmodat(int dfd, const char __user *filename, umode_t mode,
|
||||||
@ -865,14 +850,12 @@ int vfs_fchown(struct file *file, uid_t user, gid_t group)
|
|||||||
|
|
||||||
int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
|
int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int error = -EBADF;
|
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
error = vfs_fchown(fd_file(f), user, group);
|
return -EBADF;
|
||||||
fdput(f);
|
|
||||||
}
|
return vfs_fchown(fd_file(f), user, group);
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
|
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
|
||||||
|
@ -976,21 +976,19 @@ SYSCALL_DEFINE4(quotactl_fd, unsigned int, fd, unsigned int, cmd,
|
|||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
unsigned int cmds = cmd >> SUBCMDSHIFT;
|
unsigned int cmds = cmd >> SUBCMDSHIFT;
|
||||||
unsigned int type = cmd & SUBCMDMASK;
|
unsigned int type = cmd & SUBCMDMASK;
|
||||||
struct fd f;
|
CLASS(fd_raw, f)(fd);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
f = fdget_raw(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = -EINVAL;
|
|
||||||
if (type >= MAXQUOTAS)
|
if (type >= MAXQUOTAS)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
if (quotactl_cmd_write(cmds)) {
|
if (quotactl_cmd_write(cmds)) {
|
||||||
ret = mnt_want_write(fd_file(f)->f_path.mnt);
|
ret = mnt_want_write(fd_file(f)->f_path.mnt);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb = fd_file(f)->f_path.mnt->mnt_sb;
|
sb = fd_file(f)->f_path.mnt->mnt_sb;
|
||||||
@ -1008,7 +1006,5 @@ SYSCALL_DEFINE4(quotactl_fd, unsigned int, fd, unsigned int, cmd,
|
|||||||
|
|
||||||
if (quotactl_cmd_write(cmds))
|
if (quotactl_cmd_write(cmds))
|
||||||
mnt_drop_write(fd_file(f)->f_path.mnt);
|
mnt_drop_write(fd_file(f)->f_path.mnt);
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
145
fs/read_write.c
145
fs/read_write.c
@ -386,8 +386,8 @@ EXPORT_SYMBOL(vfs_llseek);
|
|||||||
static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
|
static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
|
||||||
{
|
{
|
||||||
off_t retval;
|
off_t retval;
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
@ -397,7 +397,6 @@ static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
|
|||||||
if (res != (loff_t)retval)
|
if (res != (loff_t)retval)
|
||||||
retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
|
retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
|
||||||
}
|
}
|
||||||
fdput_pos(f);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,15 +419,14 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
|
|||||||
unsigned int, whence)
|
unsigned int, whence)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
loff_t offset;
|
loff_t offset;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
retval = -EINVAL;
|
|
||||||
if (whence > SEEK_MAX)
|
if (whence > SEEK_MAX)
|
||||||
goto out_putf;
|
return -EINVAL;
|
||||||
|
|
||||||
offset = vfs_llseek(fd_file(f), ((loff_t) offset_high << 32) | offset_low,
|
offset = vfs_llseek(fd_file(f), ((loff_t) offset_high << 32) | offset_low,
|
||||||
whence);
|
whence);
|
||||||
@ -439,8 +437,6 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
|
|||||||
if (!copy_to_user(result, &offset, sizeof(offset)))
|
if (!copy_to_user(result, &offset, sizeof(offset)))
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
out_putf:
|
|
||||||
fdput_pos(f);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -700,10 +696,10 @@ static inline loff_t *file_ppos(struct file *file)
|
|||||||
|
|
||||||
ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
|
ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (!fd_empty(f)) {
|
||||||
loff_t pos, *ppos = file_ppos(fd_file(f));
|
loff_t pos, *ppos = file_ppos(fd_file(f));
|
||||||
if (ppos) {
|
if (ppos) {
|
||||||
pos = *ppos;
|
pos = *ppos;
|
||||||
@ -712,7 +708,6 @@ ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
|
|||||||
ret = vfs_read(fd_file(f), buf, count, ppos);
|
ret = vfs_read(fd_file(f), buf, count, ppos);
|
||||||
if (ret >= 0 && ppos)
|
if (ret >= 0 && ppos)
|
||||||
fd_file(f)->f_pos = pos;
|
fd_file(f)->f_pos = pos;
|
||||||
fdput_pos(f);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -724,10 +719,10 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
|
|||||||
|
|
||||||
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count)
|
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (!fd_empty(f)) {
|
||||||
loff_t pos, *ppos = file_ppos(fd_file(f));
|
loff_t pos, *ppos = file_ppos(fd_file(f));
|
||||||
if (ppos) {
|
if (ppos) {
|
||||||
pos = *ppos;
|
pos = *ppos;
|
||||||
@ -736,7 +731,6 @@ ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count)
|
|||||||
ret = vfs_write(fd_file(f), buf, count, ppos);
|
ret = vfs_write(fd_file(f), buf, count, ppos);
|
||||||
if (ret >= 0 && ppos)
|
if (ret >= 0 && ppos)
|
||||||
fd_file(f)->f_pos = pos;
|
fd_file(f)->f_pos = pos;
|
||||||
fdput_pos(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -751,21 +745,17 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
|
|||||||
ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
|
ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
|
||||||
loff_t pos)
|
loff_t pos)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
ssize_t ret = -EBADF;
|
|
||||||
|
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
ret = -ESPIPE;
|
return -EBADF;
|
||||||
if (fd_file(f)->f_mode & FMODE_PREAD)
|
|
||||||
ret = vfs_read(fd_file(f), buf, count, &pos);
|
|
||||||
fdput(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
if (fd_file(f)->f_mode & FMODE_PREAD)
|
||||||
|
return vfs_read(fd_file(f), buf, count, &pos);
|
||||||
|
|
||||||
|
return -ESPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
|
SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
|
||||||
@ -785,21 +775,17 @@ COMPAT_SYSCALL_DEFINE5(pread64, unsigned int, fd, char __user *, buf,
|
|||||||
ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf,
|
ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf,
|
||||||
size_t count, loff_t pos)
|
size_t count, loff_t pos)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
ssize_t ret = -EBADF;
|
|
||||||
|
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
ret = -ESPIPE;
|
return -EBADF;
|
||||||
if (fd_file(f)->f_mode & FMODE_PWRITE)
|
|
||||||
ret = vfs_write(fd_file(f), buf, count, &pos);
|
|
||||||
fdput(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
if (fd_file(f)->f_mode & FMODE_PWRITE)
|
||||||
|
return vfs_write(fd_file(f), buf, count, &pos);
|
||||||
|
|
||||||
|
return -ESPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
|
SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf,
|
||||||
@ -1075,10 +1061,10 @@ out:
|
|||||||
static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
|
static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
|
||||||
unsigned long vlen, rwf_t flags)
|
unsigned long vlen, rwf_t flags)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (!fd_empty(f)) {
|
||||||
loff_t pos, *ppos = file_ppos(fd_file(f));
|
loff_t pos, *ppos = file_ppos(fd_file(f));
|
||||||
if (ppos) {
|
if (ppos) {
|
||||||
pos = *ppos;
|
pos = *ppos;
|
||||||
@ -1087,7 +1073,6 @@ static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
|
|||||||
ret = vfs_readv(fd_file(f), vec, vlen, ppos, flags);
|
ret = vfs_readv(fd_file(f), vec, vlen, ppos, flags);
|
||||||
if (ret >= 0 && ppos)
|
if (ret >= 0 && ppos)
|
||||||
fd_file(f)->f_pos = pos;
|
fd_file(f)->f_pos = pos;
|
||||||
fdput_pos(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
@ -1099,10 +1084,10 @@ static ssize_t do_readv(unsigned long fd, const struct iovec __user *vec,
|
|||||||
static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
|
static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
|
||||||
unsigned long vlen, rwf_t flags)
|
unsigned long vlen, rwf_t flags)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (!fd_empty(f)) {
|
||||||
loff_t pos, *ppos = file_ppos(fd_file(f));
|
loff_t pos, *ppos = file_ppos(fd_file(f));
|
||||||
if (ppos) {
|
if (ppos) {
|
||||||
pos = *ppos;
|
pos = *ppos;
|
||||||
@ -1111,7 +1096,6 @@ static ssize_t do_writev(unsigned long fd, const struct iovec __user *vec,
|
|||||||
ret = vfs_writev(fd_file(f), vec, vlen, ppos, flags);
|
ret = vfs_writev(fd_file(f), vec, vlen, ppos, flags);
|
||||||
if (ret >= 0 && ppos)
|
if (ret >= 0 && ppos)
|
||||||
fd_file(f)->f_pos = pos;
|
fd_file(f)->f_pos = pos;
|
||||||
fdput_pos(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
@ -1129,18 +1113,16 @@ static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
|
|||||||
static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
|
static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
|
||||||
unsigned long vlen, loff_t pos, rwf_t flags)
|
unsigned long vlen, loff_t pos, rwf_t flags)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (fd_file(f)) {
|
if (!fd_empty(f)) {
|
||||||
ret = -ESPIPE;
|
ret = -ESPIPE;
|
||||||
if (fd_file(f)->f_mode & FMODE_PREAD)
|
if (fd_file(f)->f_mode & FMODE_PREAD)
|
||||||
ret = vfs_readv(fd_file(f), vec, vlen, &pos, flags);
|
ret = vfs_readv(fd_file(f), vec, vlen, &pos, flags);
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
@ -1152,18 +1134,16 @@ static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
|
|||||||
static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
|
static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
|
||||||
unsigned long vlen, loff_t pos, rwf_t flags)
|
unsigned long vlen, loff_t pos, rwf_t flags)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (fd_file(f)) {
|
if (!fd_empty(f)) {
|
||||||
ret = -ESPIPE;
|
ret = -ESPIPE;
|
||||||
if (fd_file(f)->f_mode & FMODE_PWRITE)
|
if (fd_file(f)->f_mode & FMODE_PWRITE)
|
||||||
ret = vfs_writev(fd_file(f), vec, vlen, &pos, flags);
|
ret = vfs_writev(fd_file(f), vec, vlen, &pos, flags);
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
@ -1315,7 +1295,6 @@ COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd,
|
|||||||
static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
|
static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
|
||||||
size_t count, loff_t max)
|
size_t count, loff_t max)
|
||||||
{
|
{
|
||||||
struct fd in, out;
|
|
||||||
struct inode *in_inode, *out_inode;
|
struct inode *in_inode, *out_inode;
|
||||||
struct pipe_inode_info *opipe;
|
struct pipe_inode_info *opipe;
|
||||||
loff_t pos;
|
loff_t pos;
|
||||||
@ -1326,35 +1305,32 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
|
|||||||
/*
|
/*
|
||||||
* Get input file, and verify that it is ok..
|
* Get input file, and verify that it is ok..
|
||||||
*/
|
*/
|
||||||
retval = -EBADF;
|
CLASS(fd, in)(in_fd);
|
||||||
in = fdget(in_fd);
|
if (fd_empty(in))
|
||||||
if (!fd_file(in))
|
return -EBADF;
|
||||||
goto out;
|
|
||||||
if (!(fd_file(in)->f_mode & FMODE_READ))
|
if (!(fd_file(in)->f_mode & FMODE_READ))
|
||||||
goto fput_in;
|
return -EBADF;
|
||||||
retval = -ESPIPE;
|
|
||||||
if (!ppos) {
|
if (!ppos) {
|
||||||
pos = fd_file(in)->f_pos;
|
pos = fd_file(in)->f_pos;
|
||||||
} else {
|
} else {
|
||||||
pos = *ppos;
|
pos = *ppos;
|
||||||
if (!(fd_file(in)->f_mode & FMODE_PREAD))
|
if (!(fd_file(in)->f_mode & FMODE_PREAD))
|
||||||
goto fput_in;
|
return -ESPIPE;
|
||||||
}
|
}
|
||||||
retval = rw_verify_area(READ, fd_file(in), &pos, count);
|
retval = rw_verify_area(READ, fd_file(in), &pos, count);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto fput_in;
|
return retval;
|
||||||
if (count > MAX_RW_COUNT)
|
if (count > MAX_RW_COUNT)
|
||||||
count = MAX_RW_COUNT;
|
count = MAX_RW_COUNT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get output file, and verify that it is ok..
|
* Get output file, and verify that it is ok..
|
||||||
*/
|
*/
|
||||||
retval = -EBADF;
|
CLASS(fd, out)(out_fd);
|
||||||
out = fdget(out_fd);
|
if (fd_empty(out))
|
||||||
if (!fd_file(out))
|
return -EBADF;
|
||||||
goto fput_in;
|
|
||||||
if (!(fd_file(out)->f_mode & FMODE_WRITE))
|
if (!(fd_file(out)->f_mode & FMODE_WRITE))
|
||||||
goto fput_out;
|
return -EBADF;
|
||||||
in_inode = file_inode(fd_file(in));
|
in_inode = file_inode(fd_file(in));
|
||||||
out_inode = file_inode(fd_file(out));
|
out_inode = file_inode(fd_file(out));
|
||||||
out_pos = fd_file(out)->f_pos;
|
out_pos = fd_file(out)->f_pos;
|
||||||
@ -1363,9 +1339,8 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
|
|||||||
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
|
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
|
||||||
|
|
||||||
if (unlikely(pos + count > max)) {
|
if (unlikely(pos + count > max)) {
|
||||||
retval = -EOVERFLOW;
|
|
||||||
if (pos >= max)
|
if (pos >= max)
|
||||||
goto fput_out;
|
return -EOVERFLOW;
|
||||||
count = max - pos;
|
count = max - pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1384,7 +1359,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
|
|||||||
if (!opipe) {
|
if (!opipe) {
|
||||||
retval = rw_verify_area(WRITE, fd_file(out), &out_pos, count);
|
retval = rw_verify_area(WRITE, fd_file(out), &out_pos, count);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto fput_out;
|
return retval;
|
||||||
retval = do_splice_direct(fd_file(in), &pos, fd_file(out), &out_pos,
|
retval = do_splice_direct(fd_file(in), &pos, fd_file(out), &out_pos,
|
||||||
count, fl);
|
count, fl);
|
||||||
} else {
|
} else {
|
||||||
@ -1410,12 +1385,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
|
|||||||
inc_syscw(current);
|
inc_syscw(current);
|
||||||
if (pos > max)
|
if (pos > max)
|
||||||
retval = -EOVERFLOW;
|
retval = -EOVERFLOW;
|
||||||
|
|
||||||
fput_out:
|
|
||||||
fdput(out);
|
|
||||||
fput_in:
|
|
||||||
fdput(in);
|
|
||||||
out:
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1671,36 +1640,32 @@ SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
|
|||||||
{
|
{
|
||||||
loff_t pos_in;
|
loff_t pos_in;
|
||||||
loff_t pos_out;
|
loff_t pos_out;
|
||||||
struct fd f_in;
|
|
||||||
struct fd f_out;
|
|
||||||
ssize_t ret = -EBADF;
|
ssize_t ret = -EBADF;
|
||||||
|
|
||||||
f_in = fdget(fd_in);
|
CLASS(fd, f_in)(fd_in);
|
||||||
if (!fd_file(f_in))
|
if (fd_empty(f_in))
|
||||||
goto out2;
|
return -EBADF;
|
||||||
|
|
||||||
f_out = fdget(fd_out);
|
CLASS(fd, f_out)(fd_out);
|
||||||
if (!fd_file(f_out))
|
if (fd_empty(f_out))
|
||||||
goto out1;
|
return -EBADF;
|
||||||
|
|
||||||
ret = -EFAULT;
|
|
||||||
if (off_in) {
|
if (off_in) {
|
||||||
if (copy_from_user(&pos_in, off_in, sizeof(loff_t)))
|
if (copy_from_user(&pos_in, off_in, sizeof(loff_t)))
|
||||||
goto out;
|
return -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
pos_in = fd_file(f_in)->f_pos;
|
pos_in = fd_file(f_in)->f_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (off_out) {
|
if (off_out) {
|
||||||
if (copy_from_user(&pos_out, off_out, sizeof(loff_t)))
|
if (copy_from_user(&pos_out, off_out, sizeof(loff_t)))
|
||||||
goto out;
|
return -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
pos_out = fd_file(f_out)->f_pos;
|
pos_out = fd_file(f_out)->f_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = -EINVAL;
|
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = vfs_copy_file_range(fd_file(f_in), pos_in, fd_file(f_out), pos_out, len,
|
ret = vfs_copy_file_range(fd_file(f_in), pos_in, fd_file(f_out), pos_out, len,
|
||||||
flags);
|
flags);
|
||||||
@ -1722,12 +1687,6 @@ SYSCALL_DEFINE6(copy_file_range, int, fd_in, loff_t __user *, off_in,
|
|||||||
fd_file(f_out)->f_pos = pos_out;
|
fd_file(f_out)->f_pos = pos_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
fdput(f_out);
|
|
||||||
out1:
|
|
||||||
fdput(f_in);
|
|
||||||
out2:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
fs/readdir.c
28
fs/readdir.c
@ -219,20 +219,19 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
|
|||||||
struct old_linux_dirent __user *, dirent, unsigned int, count)
|
struct old_linux_dirent __user *, dirent, unsigned int, count)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
struct readdir_callback buf = {
|
struct readdir_callback buf = {
|
||||||
.ctx.actor = fillonedir,
|
.ctx.actor = fillonedir,
|
||||||
.dirent = dirent
|
.dirent = dirent
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = iterate_dir(fd_file(f), &buf.ctx);
|
error = iterate_dir(fd_file(f), &buf.ctx);
|
||||||
if (buf.result)
|
if (buf.result)
|
||||||
error = buf.result;
|
error = buf.result;
|
||||||
|
|
||||||
fdput_pos(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +308,7 @@ efault:
|
|||||||
SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
||||||
struct linux_dirent __user *, dirent, unsigned int, count)
|
struct linux_dirent __user *, dirent, unsigned int, count)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd_pos, f)(fd);
|
||||||
struct getdents_callback buf = {
|
struct getdents_callback buf = {
|
||||||
.ctx.actor = filldir,
|
.ctx.actor = filldir,
|
||||||
.count = count,
|
.count = count,
|
||||||
@ -317,8 +316,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
};
|
};
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
f = fdget_pos(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = iterate_dir(fd_file(f), &buf.ctx);
|
error = iterate_dir(fd_file(f), &buf.ctx);
|
||||||
@ -333,7 +331,6 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fdput_pos(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +389,7 @@ efault:
|
|||||||
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
||||||
struct linux_dirent64 __user *, dirent, unsigned int, count)
|
struct linux_dirent64 __user *, dirent, unsigned int, count)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd_pos, f)(fd);
|
||||||
struct getdents_callback64 buf = {
|
struct getdents_callback64 buf = {
|
||||||
.ctx.actor = filldir64,
|
.ctx.actor = filldir64,
|
||||||
.count = count,
|
.count = count,
|
||||||
@ -400,8 +397,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
|||||||
};
|
};
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
f = fdget_pos(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = iterate_dir(fd_file(f), &buf.ctx);
|
error = iterate_dir(fd_file(f), &buf.ctx);
|
||||||
@ -417,7 +413,6 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
|||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fdput_pos(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,20 +472,19 @@ COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
|
|||||||
struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
|
struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct fd f = fdget_pos(fd);
|
CLASS(fd_pos, f)(fd);
|
||||||
struct compat_readdir_callback buf = {
|
struct compat_readdir_callback buf = {
|
||||||
.ctx.actor = compat_fillonedir,
|
.ctx.actor = compat_fillonedir,
|
||||||
.dirent = dirent
|
.dirent = dirent
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = iterate_dir(fd_file(f), &buf.ctx);
|
error = iterate_dir(fd_file(f), &buf.ctx);
|
||||||
if (buf.result)
|
if (buf.result)
|
||||||
error = buf.result;
|
error = buf.result;
|
||||||
|
|
||||||
fdput_pos(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +554,7 @@ efault:
|
|||||||
COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
||||||
struct compat_linux_dirent __user *, dirent, unsigned int, count)
|
struct compat_linux_dirent __user *, dirent, unsigned int, count)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd_pos, f)(fd);
|
||||||
struct compat_getdents_callback buf = {
|
struct compat_getdents_callback buf = {
|
||||||
.ctx.actor = compat_filldir,
|
.ctx.actor = compat_filldir,
|
||||||
.current_dir = dirent,
|
.current_dir = dirent,
|
||||||
@ -568,8 +562,7 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
};
|
};
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
f = fdget_pos(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
error = iterate_dir(fd_file(f), &buf.ctx);
|
error = iterate_dir(fd_file(f), &buf.ctx);
|
||||||
@ -584,7 +577,6 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
|||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fdput_pos(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -536,20 +536,19 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, info = same->info; i < count; i++, info++) {
|
for (i = 0, info = same->info; i < count; i++, info++) {
|
||||||
struct fd dst_fd = fdget(info->dest_fd);
|
CLASS(fd, dst_fd)(info->dest_fd);
|
||||||
struct file *dst_file = fd_file(dst_fd);
|
|
||||||
|
|
||||||
if (!dst_file) {
|
if (fd_empty(dst_fd)) {
|
||||||
info->status = -EBADF;
|
info->status = -EBADF;
|
||||||
goto next_loop;
|
goto next_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->reserved) {
|
if (info->reserved) {
|
||||||
info->status = -EINVAL;
|
info->status = -EINVAL;
|
||||||
goto next_fdput;
|
goto next_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
deduped = vfs_dedupe_file_range_one(file, off, dst_file,
|
deduped = vfs_dedupe_file_range_one(file, off, fd_file(dst_fd),
|
||||||
info->dest_offset, len,
|
info->dest_offset, len,
|
||||||
REMAP_FILE_CAN_SHORTEN);
|
REMAP_FILE_CAN_SHORTEN);
|
||||||
if (deduped == -EBADE)
|
if (deduped == -EBADE)
|
||||||
@ -559,8 +558,6 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
|
|||||||
else
|
else
|
||||||
info->bytes_deduped = len;
|
info->bytes_deduped = len;
|
||||||
|
|
||||||
next_fdput:
|
|
||||||
fdput(dst_fd);
|
|
||||||
next_loop:
|
next_loop:
|
||||||
if (fatal_signal_pending(current))
|
if (fatal_signal_pending(current))
|
||||||
break;
|
break;
|
||||||
|
48
fs/select.c
48
fs/select.c
@ -462,15 +462,22 @@ get_max:
|
|||||||
EPOLLNVAL)
|
EPOLLNVAL)
|
||||||
#define POLLEX_SET (EPOLLPRI | EPOLLNVAL)
|
#define POLLEX_SET (EPOLLPRI | EPOLLNVAL)
|
||||||
|
|
||||||
static inline void wait_key_set(poll_table *wait, unsigned long in,
|
static inline __poll_t select_poll_one(int fd, poll_table *wait, unsigned long in,
|
||||||
unsigned long out, unsigned long bit,
|
unsigned long out, unsigned long bit,
|
||||||
__poll_t ll_flag)
|
__poll_t ll_flag)
|
||||||
{
|
{
|
||||||
|
CLASS(fd, f)(fd);
|
||||||
|
|
||||||
|
if (fd_empty(f))
|
||||||
|
return EPOLLNVAL;
|
||||||
|
|
||||||
wait->_key = POLLEX_SET | ll_flag;
|
wait->_key = POLLEX_SET | ll_flag;
|
||||||
if (in & bit)
|
if (in & bit)
|
||||||
wait->_key |= POLLIN_SET;
|
wait->_key |= POLLIN_SET;
|
||||||
if (out & bit)
|
if (out & bit)
|
||||||
wait->_key |= POLLOUT_SET;
|
wait->_key |= POLLOUT_SET;
|
||||||
|
|
||||||
|
return vfs_poll(fd_file(f), wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
|
static noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
|
||||||
@ -522,20 +529,12 @@ static noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) {
|
for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) {
|
||||||
struct fd f;
|
|
||||||
if (i >= n)
|
if (i >= n)
|
||||||
break;
|
break;
|
||||||
if (!(bit & all_bits))
|
if (!(bit & all_bits))
|
||||||
continue;
|
continue;
|
||||||
mask = EPOLLNVAL;
|
mask = select_poll_one(i, wait, in, out, bit,
|
||||||
f = fdget(i);
|
busy_flag);
|
||||||
if (fd_file(f)) {
|
|
||||||
wait_key_set(wait, in, out, bit,
|
|
||||||
busy_flag);
|
|
||||||
mask = vfs_poll(fd_file(f), wait);
|
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
}
|
|
||||||
if ((mask & POLLIN_SET) && (in & bit)) {
|
if ((mask & POLLIN_SET) && (in & bit)) {
|
||||||
res_in |= bit;
|
res_in |= bit;
|
||||||
retval++;
|
retval++;
|
||||||
@ -856,15 +855,14 @@ static inline __poll_t do_pollfd(struct pollfd *pollfd, poll_table *pwait,
|
|||||||
__poll_t busy_flag)
|
__poll_t busy_flag)
|
||||||
{
|
{
|
||||||
int fd = pollfd->fd;
|
int fd = pollfd->fd;
|
||||||
__poll_t mask = 0, filter;
|
__poll_t mask, filter;
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
goto out;
|
return 0;
|
||||||
mask = EPOLLNVAL;
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
goto out;
|
return EPOLLNVAL;
|
||||||
|
|
||||||
/* userland u16 ->events contains POLL... bitmap */
|
/* userland u16 ->events contains POLL... bitmap */
|
||||||
filter = demangle_poll(pollfd->events) | EPOLLERR | EPOLLHUP;
|
filter = demangle_poll(pollfd->events) | EPOLLERR | EPOLLHUP;
|
||||||
@ -872,13 +870,7 @@ static inline __poll_t do_pollfd(struct pollfd *pollfd, poll_table *pwait,
|
|||||||
mask = vfs_poll(fd_file(f), pwait);
|
mask = vfs_poll(fd_file(f), pwait);
|
||||||
if (mask & busy_flag)
|
if (mask & busy_flag)
|
||||||
*can_busy_poll = true;
|
*can_busy_poll = true;
|
||||||
mask &= filter; /* Mask out unneeded events. */
|
return mask & filter; /* Mask out unneeded events. */
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
out:
|
|
||||||
/* ... and so does ->revents */
|
|
||||||
pollfd->revents = mangle_poll(mask);
|
|
||||||
return mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_poll(struct poll_list *list, struct poll_wqueues *wait,
|
static int do_poll(struct poll_list *list, struct poll_wqueues *wait,
|
||||||
@ -910,6 +902,7 @@ static int do_poll(struct poll_list *list, struct poll_wqueues *wait,
|
|||||||
pfd = walk->entries;
|
pfd = walk->entries;
|
||||||
pfd_end = pfd + walk->len;
|
pfd_end = pfd + walk->len;
|
||||||
for (; pfd != pfd_end; pfd++) {
|
for (; pfd != pfd_end; pfd++) {
|
||||||
|
__poll_t mask;
|
||||||
/*
|
/*
|
||||||
* Fish for events. If we found one, record it
|
* Fish for events. If we found one, record it
|
||||||
* and kill poll_table->_qproc, so we don't
|
* and kill poll_table->_qproc, so we don't
|
||||||
@ -917,8 +910,9 @@ static int do_poll(struct poll_list *list, struct poll_wqueues *wait,
|
|||||||
* this. They'll get immediately deregistered
|
* this. They'll get immediately deregistered
|
||||||
* when we break out and return.
|
* when we break out and return.
|
||||||
*/
|
*/
|
||||||
if (do_pollfd(pfd, pt, &can_busy_loop,
|
mask = do_pollfd(pfd, pt, &can_busy_loop, busy_flag);
|
||||||
busy_flag)) {
|
pfd->revents = mangle_poll(mask);
|
||||||
|
if (mask) {
|
||||||
count++;
|
count++;
|
||||||
pt->_qproc = NULL;
|
pt->_qproc = NULL;
|
||||||
/* found something, stop busy polling */
|
/* found something, stop busy polling */
|
||||||
|
@ -288,20 +288,17 @@ static int do_signalfd4(int ufd, sigset_t *mask, int flags)
|
|||||||
|
|
||||||
fd_install(ufd, file);
|
fd_install(ufd, file);
|
||||||
} else {
|
} else {
|
||||||
struct fd f = fdget(ufd);
|
CLASS(fd, f)(ufd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
ctx = fd_file(f)->private_data;
|
ctx = fd_file(f)->private_data;
|
||||||
if (fd_file(f)->f_op != &signalfd_fops) {
|
if (fd_file(f)->f_op != &signalfd_fops)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
ctx->sigmask = *mask;
|
ctx->sigmask = *mask;
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
wake_up(¤t->sighand->signalfd_wqh);
|
wake_up(¤t->sighand->signalfd_wqh);
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ufd;
|
return ufd;
|
||||||
|
@ -72,7 +72,6 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
|
|||||||
unsigned long srcfd)
|
unsigned long srcfd)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct fd src_file;
|
|
||||||
struct inode *src_inode;
|
struct inode *src_inode;
|
||||||
|
|
||||||
cifs_dbg(FYI, "ioctl copychunk range\n");
|
cifs_dbg(FYI, "ioctl copychunk range\n");
|
||||||
@ -89,8 +88,8 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
src_file = fdget(srcfd);
|
CLASS(fd, src_file)(srcfd);
|
||||||
if (!fd_file(src_file)) {
|
if (fd_empty(src_file)) {
|
||||||
rc = -EBADF;
|
rc = -EBADF;
|
||||||
goto out_drop_write;
|
goto out_drop_write;
|
||||||
}
|
}
|
||||||
@ -98,20 +97,18 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
|
|||||||
if (fd_file(src_file)->f_op->unlocked_ioctl != cifs_ioctl) {
|
if (fd_file(src_file)->f_op->unlocked_ioctl != cifs_ioctl) {
|
||||||
rc = -EBADF;
|
rc = -EBADF;
|
||||||
cifs_dbg(VFS, "src file seems to be from a different filesystem type\n");
|
cifs_dbg(VFS, "src file seems to be from a different filesystem type\n");
|
||||||
goto out_fput;
|
goto out_drop_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
src_inode = file_inode(fd_file(src_file));
|
src_inode = file_inode(fd_file(src_file));
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
if (S_ISDIR(src_inode->i_mode))
|
if (S_ISDIR(src_inode->i_mode))
|
||||||
goto out_fput;
|
goto out_drop_write;
|
||||||
|
|
||||||
rc = cifs_file_copychunk_range(xid, fd_file(src_file), 0, dst_file, 0,
|
rc = cifs_file_copychunk_range(xid, fd_file(src_file), 0, dst_file, 0,
|
||||||
src_inode->i_size, 0);
|
src_inode->i_size, 0);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
out_fput:
|
|
||||||
fdput(src_file);
|
|
||||||
out_drop_write:
|
out_drop_write:
|
||||||
mnt_drop_write_file(dst_file);
|
mnt_drop_write_file(dst_file);
|
||||||
return rc;
|
return rc;
|
||||||
|
78
fs/splice.c
78
fs/splice.c
@ -1564,21 +1564,6 @@ static ssize_t vmsplice_to_pipe(struct file *file, struct iov_iter *iter,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmsplice_type(struct fd f, int *type)
|
|
||||||
{
|
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
|
||||||
if (fd_file(f)->f_mode & FMODE_WRITE) {
|
|
||||||
*type = ITER_SOURCE;
|
|
||||||
} else if (fd_file(f)->f_mode & FMODE_READ) {
|
|
||||||
*type = ITER_DEST;
|
|
||||||
} else {
|
|
||||||
fdput(f);
|
|
||||||
return -EBADF;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that vmsplice only really supports true splicing _from_ user memory
|
* Note that vmsplice only really supports true splicing _from_ user memory
|
||||||
* to a pipe, not the other way around. Splicing from user memory is a simple
|
* to a pipe, not the other way around. Splicing from user memory is a simple
|
||||||
@ -1602,21 +1587,25 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
|
|||||||
struct iovec *iov = iovstack;
|
struct iovec *iov = iovstack;
|
||||||
struct iov_iter iter;
|
struct iov_iter iter;
|
||||||
ssize_t error;
|
ssize_t error;
|
||||||
struct fd f;
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
if (unlikely(flags & ~SPLICE_F_ALL))
|
if (unlikely(flags & ~SPLICE_F_ALL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
error = vmsplice_type(f, &type);
|
if (fd_empty(f))
|
||||||
if (error)
|
return -EBADF;
|
||||||
return error;
|
if (fd_file(f)->f_mode & FMODE_WRITE)
|
||||||
|
type = ITER_SOURCE;
|
||||||
|
else if (fd_file(f)->f_mode & FMODE_READ)
|
||||||
|
type = ITER_DEST;
|
||||||
|
else
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
error = import_iovec(type, uiov, nr_segs,
|
error = import_iovec(type, uiov, nr_segs,
|
||||||
ARRAY_SIZE(iovstack), &iov, &iter);
|
ARRAY_SIZE(iovstack), &iov, &iter);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto out_fdput;
|
return error;
|
||||||
|
|
||||||
if (!iov_iter_count(&iter))
|
if (!iov_iter_count(&iter))
|
||||||
error = 0;
|
error = 0;
|
||||||
@ -1626,8 +1615,6 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
|
|||||||
error = vmsplice_to_user(fd_file(f), &iter, flags);
|
error = vmsplice_to_user(fd_file(f), &iter, flags);
|
||||||
|
|
||||||
kfree(iov);
|
kfree(iov);
|
||||||
out_fdput:
|
|
||||||
fdput(f);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1635,27 +1622,22 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
|
|||||||
int, fd_out, loff_t __user *, off_out,
|
int, fd_out, loff_t __user *, off_out,
|
||||||
size_t, len, unsigned int, flags)
|
size_t, len, unsigned int, flags)
|
||||||
{
|
{
|
||||||
struct fd in, out;
|
|
||||||
ssize_t error;
|
|
||||||
|
|
||||||
if (unlikely(!len))
|
if (unlikely(!len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (unlikely(flags & ~SPLICE_F_ALL))
|
if (unlikely(flags & ~SPLICE_F_ALL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
error = -EBADF;
|
CLASS(fd, in)(fd_in);
|
||||||
in = fdget(fd_in);
|
if (fd_empty(in))
|
||||||
if (fd_file(in)) {
|
return -EBADF;
|
||||||
out = fdget(fd_out);
|
|
||||||
if (fd_file(out)) {
|
CLASS(fd, out)(fd_out);
|
||||||
error = __do_splice(fd_file(in), off_in, fd_file(out), off_out,
|
if (fd_empty(out))
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
return __do_splice(fd_file(in), off_in, fd_file(out), off_out,
|
||||||
len, flags);
|
len, flags);
|
||||||
fdput(out);
|
|
||||||
}
|
|
||||||
fdput(in);
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2005,25 +1987,19 @@ ssize_t do_tee(struct file *in, struct file *out, size_t len,
|
|||||||
|
|
||||||
SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
|
SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
|
||||||
{
|
{
|
||||||
struct fd in, out;
|
|
||||||
ssize_t error;
|
|
||||||
|
|
||||||
if (unlikely(flags & ~SPLICE_F_ALL))
|
if (unlikely(flags & ~SPLICE_F_ALL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (unlikely(!len))
|
if (unlikely(!len))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error = -EBADF;
|
CLASS(fd, in)(fdin);
|
||||||
in = fdget(fdin);
|
if (fd_empty(in))
|
||||||
if (fd_file(in)) {
|
return -EBADF;
|
||||||
out = fdget(fdout);
|
|
||||||
if (fd_file(out)) {
|
|
||||||
error = do_tee(fd_file(in), fd_file(out), len, flags);
|
|
||||||
fdput(out);
|
|
||||||
}
|
|
||||||
fdput(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
CLASS(fd, out)(fdout);
|
||||||
|
if (fd_empty(out))
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
return do_tee(fd_file(in), fd_file(out), len, flags);
|
||||||
}
|
}
|
||||||
|
12
fs/statfs.c
12
fs/statfs.c
@ -114,13 +114,11 @@ retry:
|
|||||||
|
|
||||||
int fd_statfs(int fd, struct kstatfs *st)
|
int fd_statfs(int fd, struct kstatfs *st)
|
||||||
{
|
{
|
||||||
struct fd f = fdget_raw(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
int error = -EBADF;
|
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
error = vfs_statfs(&fd_file(f)->f_path, st);
|
return -EBADF;
|
||||||
fdput(f);
|
return vfs_statfs(&fd_file(f)->f_path, st);
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
|
static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
|
||||||
|
29
fs/sync.c
29
fs/sync.c
@ -148,11 +148,11 @@ void emergency_sync(void)
|
|||||||
*/
|
*/
|
||||||
SYSCALL_DEFINE1(syncfs, int, fd)
|
SYSCALL_DEFINE1(syncfs, int, fd)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
int ret, ret2;
|
int ret, ret2;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
sb = fd_file(f)->f_path.dentry->d_sb;
|
sb = fd_file(f)->f_path.dentry->d_sb;
|
||||||
|
|
||||||
@ -162,7 +162,6 @@ SYSCALL_DEFINE1(syncfs, int, fd)
|
|||||||
|
|
||||||
ret2 = errseq_check_and_advance(&sb->s_wb_err, &fd_file(f)->f_sb_err);
|
ret2 = errseq_check_and_advance(&sb->s_wb_err, &fd_file(f)->f_sb_err);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return ret ? ret : ret2;
|
return ret ? ret : ret2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,14 +204,12 @@ EXPORT_SYMBOL(vfs_fsync);
|
|||||||
|
|
||||||
static int do_fsync(unsigned int fd, int datasync)
|
static int do_fsync(unsigned int fd, int datasync)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int ret = -EBADF;
|
|
||||||
|
|
||||||
if (fd_file(f)) {
|
if (fd_empty(f))
|
||||||
ret = vfs_fsync(fd_file(f), datasync);
|
return -EBADF;
|
||||||
fdput(f);
|
|
||||||
}
|
return vfs_fsync(fd_file(f), datasync);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE1(fsync, unsigned int, fd)
|
SYSCALL_DEFINE1(fsync, unsigned int, fd)
|
||||||
@ -355,16 +352,12 @@ out:
|
|||||||
int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
|
int ksys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
int ret;
|
CLASS(fd, f)(fd);
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
ret = -EBADF;
|
if (fd_empty(f))
|
||||||
f = fdget(fd);
|
return -EBADF;
|
||||||
if (fd_file(f))
|
|
||||||
ret = sync_file_range(fd_file(f), offset, nbytes, flags);
|
|
||||||
|
|
||||||
fdput(f);
|
return sync_file_range(fd_file(f), offset, nbytes, flags);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
|
SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
|
||||||
|
40
fs/timerfd.c
40
fs/timerfd.c
@ -394,19 +394,6 @@ static const struct file_operations timerfd_fops = {
|
|||||||
.unlocked_ioctl = timerfd_ioctl,
|
.unlocked_ioctl = timerfd_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int timerfd_fget(int fd, struct fd *p)
|
|
||||||
{
|
|
||||||
struct fd f = fdget(fd);
|
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
|
||||||
if (fd_file(f)->f_op != &timerfd_fops) {
|
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
*p = f;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
|
SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
|
||||||
{
|
{
|
||||||
int ufd;
|
int ufd;
|
||||||
@ -471,7 +458,6 @@ static int do_timerfd_settime(int ufd, int flags,
|
|||||||
const struct itimerspec64 *new,
|
const struct itimerspec64 *new,
|
||||||
struct itimerspec64 *old)
|
struct itimerspec64 *old)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
struct timerfd_ctx *ctx;
|
struct timerfd_ctx *ctx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -479,15 +465,17 @@ static int do_timerfd_settime(int ufd, int flags,
|
|||||||
!itimerspec64_valid(new))
|
!itimerspec64_valid(new))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = timerfd_fget(ufd, &f);
|
CLASS(fd, f)(ufd);
|
||||||
if (ret)
|
if (fd_empty(f))
|
||||||
return ret;
|
return -EBADF;
|
||||||
|
|
||||||
|
if (fd_file(f)->f_op != &timerfd_fops)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
ctx = fd_file(f)->private_data;
|
ctx = fd_file(f)->private_data;
|
||||||
|
|
||||||
if (isalarm(ctx) && !capable(CAP_WAKE_ALARM)) {
|
if (isalarm(ctx) && !capable(CAP_WAKE_ALARM))
|
||||||
fdput(f);
|
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
|
||||||
|
|
||||||
timerfd_setup_cancel(ctx, flags);
|
timerfd_setup_cancel(ctx, flags);
|
||||||
|
|
||||||
@ -535,17 +523,18 @@ static int do_timerfd_settime(int ufd, int flags,
|
|||||||
ret = timerfd_setup(ctx, flags, new);
|
ret = timerfd_setup(ctx, flags, new);
|
||||||
|
|
||||||
spin_unlock_irq(&ctx->wqh.lock);
|
spin_unlock_irq(&ctx->wqh.lock);
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_timerfd_gettime(int ufd, struct itimerspec64 *t)
|
static int do_timerfd_gettime(int ufd, struct itimerspec64 *t)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
struct timerfd_ctx *ctx;
|
struct timerfd_ctx *ctx;
|
||||||
int ret = timerfd_fget(ufd, &f);
|
CLASS(fd, f)(ufd);
|
||||||
if (ret)
|
|
||||||
return ret;
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
if (fd_file(f)->f_op != &timerfd_fops)
|
||||||
|
return -EINVAL;
|
||||||
ctx = fd_file(f)->private_data;
|
ctx = fd_file(f)->private_data;
|
||||||
|
|
||||||
spin_lock_irq(&ctx->wqh.lock);
|
spin_lock_irq(&ctx->wqh.lock);
|
||||||
@ -567,7 +556,6 @@ static int do_timerfd_gettime(int ufd, struct itimerspec64 *t)
|
|||||||
t->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx));
|
t->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx));
|
||||||
t->it_interval = ktime_to_timespec64(ctx->tintv);
|
t->it_interval = ktime_to_timespec64(ctx->tintv);
|
||||||
spin_unlock_irq(&ctx->wqh.lock);
|
spin_unlock_irq(&ctx->wqh.lock);
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
fs/utimes.c
11
fs/utimes.c
@ -108,18 +108,13 @@ retry:
|
|||||||
|
|
||||||
static int do_utimes_fd(int fd, struct timespec64 *times, int flags)
|
static int do_utimes_fd(int fd, struct timespec64 *times, int flags)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
error = vfs_utimes(&fd_file(f)->f_path, times);
|
return vfs_utimes(&fd_file(f)->f_path, times);
|
||||||
fdput(f);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -813,8 +813,6 @@ xfs_ioc_exchange_range(
|
|||||||
.file2 = file,
|
.file2 = file,
|
||||||
};
|
};
|
||||||
struct xfs_exchange_range args;
|
struct xfs_exchange_range args;
|
||||||
struct fd file1;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (copy_from_user(&args, argp, sizeof(args)))
|
if (copy_from_user(&args, argp, sizeof(args)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -828,14 +826,12 @@ xfs_ioc_exchange_range(
|
|||||||
fxr.length = args.length;
|
fxr.length = args.length;
|
||||||
fxr.flags = args.flags;
|
fxr.flags = args.flags;
|
||||||
|
|
||||||
file1 = fdget(args.file1_fd);
|
CLASS(fd, file1)(args.file1_fd);
|
||||||
if (!fd_file(file1))
|
if (fd_empty(file1))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
fxr.file1 = fd_file(file1);
|
fxr.file1 = fd_file(file1);
|
||||||
|
|
||||||
error = xfs_exchange_range(&fxr);
|
return xfs_exchange_range(&fxr);
|
||||||
fdput(file1);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opaque freshness blob for XFS_IOC_COMMIT_RANGE */
|
/* Opaque freshness blob for XFS_IOC_COMMIT_RANGE */
|
||||||
@ -909,8 +905,6 @@ xfs_ioc_commit_range(
|
|||||||
struct xfs_commit_range_fresh *kern_f;
|
struct xfs_commit_range_fresh *kern_f;
|
||||||
struct xfs_inode *ip2 = XFS_I(file_inode(file));
|
struct xfs_inode *ip2 = XFS_I(file_inode(file));
|
||||||
struct xfs_mount *mp = ip2->i_mount;
|
struct xfs_mount *mp = ip2->i_mount;
|
||||||
struct fd file1;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
kern_f = (struct xfs_commit_range_fresh *)&args.file2_freshness;
|
kern_f = (struct xfs_commit_range_fresh *)&args.file2_freshness;
|
||||||
|
|
||||||
@ -934,12 +928,10 @@ xfs_ioc_commit_range(
|
|||||||
fxr.file2_ctime.tv_sec = kern_f->file2_ctime;
|
fxr.file2_ctime.tv_sec = kern_f->file2_ctime;
|
||||||
fxr.file2_ctime.tv_nsec = kern_f->file2_ctime_nsec;
|
fxr.file2_ctime.tv_nsec = kern_f->file2_ctime_nsec;
|
||||||
|
|
||||||
file1 = fdget(args.file1_fd);
|
CLASS(fd, file1)(args.file1_fd);
|
||||||
if (fd_empty(file1))
|
if (fd_empty(file1))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
fxr.file1 = fd_file(file1);
|
fxr.file1 = fd_file(file1);
|
||||||
|
|
||||||
error = xfs_exchange_range(&fxr);
|
return xfs_exchange_range(&fxr);
|
||||||
fdput(file1);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
@ -85,22 +85,23 @@ xfs_find_handle(
|
|||||||
int hsize;
|
int hsize;
|
||||||
xfs_handle_t handle;
|
xfs_handle_t handle;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct fd f = EMPTY_FD;
|
|
||||||
struct path path;
|
struct path path;
|
||||||
int error;
|
int error;
|
||||||
struct xfs_inode *ip;
|
struct xfs_inode *ip;
|
||||||
|
|
||||||
if (cmd == XFS_IOC_FD_TO_HANDLE) {
|
if (cmd == XFS_IOC_FD_TO_HANDLE) {
|
||||||
f = fdget(hreq->fd);
|
CLASS(fd, f)(hreq->fd);
|
||||||
if (!fd_file(f))
|
|
||||||
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
inode = file_inode(fd_file(f));
|
path = fd_file(f)->f_path;
|
||||||
|
path_get(&path);
|
||||||
} else {
|
} else {
|
||||||
error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
|
error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
inode = d_inode(path.dentry);
|
|
||||||
}
|
}
|
||||||
|
inode = d_inode(path.dentry);
|
||||||
ip = XFS_I(inode);
|
ip = XFS_I(inode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -134,10 +135,7 @@ xfs_find_handle(
|
|||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
out_put:
|
out_put:
|
||||||
if (cmd == XFS_IOC_FD_TO_HANDLE)
|
path_put(&path);
|
||||||
fdput(f);
|
|
||||||
else
|
|
||||||
path_put(&path);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,41 +881,29 @@ xfs_ioc_swapext(
|
|||||||
xfs_swapext_t *sxp)
|
xfs_swapext_t *sxp)
|
||||||
{
|
{
|
||||||
xfs_inode_t *ip, *tip;
|
xfs_inode_t *ip, *tip;
|
||||||
struct fd f, tmp;
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
/* Pull information for the target fd */
|
/* Pull information for the target fd */
|
||||||
f = fdget((int)sxp->sx_fdtarget);
|
CLASS(fd, f)((int)sxp->sx_fdtarget);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f))
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(fd_file(f)->f_mode & FMODE_WRITE) ||
|
if (!(fd_file(f)->f_mode & FMODE_WRITE) ||
|
||||||
!(fd_file(f)->f_mode & FMODE_READ) ||
|
!(fd_file(f)->f_mode & FMODE_READ) ||
|
||||||
(fd_file(f)->f_flags & O_APPEND)) {
|
(fd_file(f)->f_flags & O_APPEND))
|
||||||
error = -EBADF;
|
return -EBADF;
|
||||||
goto out_put_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = fdget((int)sxp->sx_fdtmp);
|
CLASS(fd, tmp)((int)sxp->sx_fdtmp);
|
||||||
if (!fd_file(tmp)) {
|
if (fd_empty(tmp))
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_put_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(fd_file(tmp)->f_mode & FMODE_WRITE) ||
|
if (!(fd_file(tmp)->f_mode & FMODE_WRITE) ||
|
||||||
!(fd_file(tmp)->f_mode & FMODE_READ) ||
|
!(fd_file(tmp)->f_mode & FMODE_READ) ||
|
||||||
(fd_file(tmp)->f_flags & O_APPEND)) {
|
(fd_file(tmp)->f_flags & O_APPEND))
|
||||||
error = -EBADF;
|
return -EBADF;
|
||||||
goto out_put_tmp_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_SWAPFILE(file_inode(fd_file(f))) ||
|
if (IS_SWAPFILE(file_inode(fd_file(f))) ||
|
||||||
IS_SWAPFILE(file_inode(fd_file(tmp)))) {
|
IS_SWAPFILE(file_inode(fd_file(tmp))))
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_put_tmp_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to ensure that the fds passed in point to XFS inodes
|
* We need to ensure that the fds passed in point to XFS inodes
|
||||||
@ -923,37 +911,22 @@ xfs_ioc_swapext(
|
|||||||
* control over what the user passes us here.
|
* control over what the user passes us here.
|
||||||
*/
|
*/
|
||||||
if (fd_file(f)->f_op != &xfs_file_operations ||
|
if (fd_file(f)->f_op != &xfs_file_operations ||
|
||||||
fd_file(tmp)->f_op != &xfs_file_operations) {
|
fd_file(tmp)->f_op != &xfs_file_operations)
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_put_tmp_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip = XFS_I(file_inode(fd_file(f)));
|
ip = XFS_I(file_inode(fd_file(f)));
|
||||||
tip = XFS_I(file_inode(fd_file(tmp)));
|
tip = XFS_I(file_inode(fd_file(tmp)));
|
||||||
|
|
||||||
if (ip->i_mount != tip->i_mount) {
|
if (ip->i_mount != tip->i_mount)
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_put_tmp_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ip->i_ino == tip->i_ino) {
|
if (ip->i_ino == tip->i_ino)
|
||||||
error = -EINVAL;
|
return -EINVAL;
|
||||||
goto out_put_tmp_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xfs_is_shutdown(ip->i_mount)) {
|
if (xfs_is_shutdown(ip->i_mount))
|
||||||
error = -EIO;
|
return -EIO;
|
||||||
goto out_put_tmp_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = xfs_swap_extents(ip, tip, sxp);
|
return xfs_swap_extents(ip, tip, sxp);
|
||||||
|
|
||||||
out_put_tmp_file:
|
|
||||||
fdput(tmp);
|
|
||||||
out_put_file:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -234,7 +234,7 @@ const volatile void * __must_check_fn(const volatile void *val)
|
|||||||
* DEFINE_CLASS(fdget, struct fd, fdput(_T), fdget(fd), int fd)
|
* DEFINE_CLASS(fdget, struct fd, fdput(_T), fdget(fd), int fd)
|
||||||
*
|
*
|
||||||
* CLASS(fdget, f)(fd);
|
* CLASS(fdget, f)(fd);
|
||||||
* if (!fd_file(f))
|
* if (fd_empty(f))
|
||||||
* return -EBADF;
|
* return -EBADF;
|
||||||
*
|
*
|
||||||
* // use 'f' without concern
|
* // use 'f' without concern
|
||||||
|
@ -30,12 +30,6 @@ extern struct file *alloc_file_pseudo_noaccount(struct inode *, struct vfsmount
|
|||||||
extern struct file *alloc_file_clone(struct file *, int flags,
|
extern struct file *alloc_file_clone(struct file *, int flags,
|
||||||
const struct file_operations *);
|
const struct file_operations *);
|
||||||
|
|
||||||
static inline void fput_light(struct file *file, int fput_needed)
|
|
||||||
{
|
|
||||||
if (fput_needed)
|
|
||||||
fput(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* either a reference to struct file + flags
|
/* either a reference to struct file + flags
|
||||||
* (cloned vs. borrowed, pos locked), with
|
* (cloned vs. borrowed, pos locked), with
|
||||||
* flags stored in lower bits of value,
|
* flags stored in lower bits of value,
|
||||||
@ -88,6 +82,7 @@ static inline void fdput_pos(struct fd f)
|
|||||||
|
|
||||||
DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)
|
DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)
|
||||||
DEFINE_CLASS(fd_raw, struct fd, fdput(_T), fdget_raw(fd), int fd)
|
DEFINE_CLASS(fd_raw, struct fd, fdput(_T), fdget_raw(fd), int fd)
|
||||||
|
DEFINE_CLASS(fd_pos, struct fd, fdput_pos(_T), fdget_pos(fd), int fd)
|
||||||
|
|
||||||
extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
|
extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
|
||||||
extern int replace_fd(unsigned fd, struct file *file, unsigned flags);
|
extern int replace_fd(unsigned fd, struct file *file, unsigned flags);
|
||||||
|
@ -239,7 +239,7 @@ int netlink_register_notifier(struct notifier_block *nb);
|
|||||||
int netlink_unregister_notifier(struct notifier_block *nb);
|
int netlink_unregister_notifier(struct notifier_block *nb);
|
||||||
|
|
||||||
/* finegrained unicast helpers: */
|
/* finegrained unicast helpers: */
|
||||||
struct sock *netlink_getsockbyfilp(struct file *filp);
|
struct sock *netlink_getsockbyfd(int fd);
|
||||||
int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
|
int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
|
||||||
long *timeo, struct sock *ssk);
|
long *timeo, struct sock *ssk);
|
||||||
void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
|
void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
|
||||||
|
@ -106,29 +106,21 @@ static struct io_sq_data *io_attach_sq_data(struct io_uring_params *p)
|
|||||||
{
|
{
|
||||||
struct io_ring_ctx *ctx_attach;
|
struct io_ring_ctx *ctx_attach;
|
||||||
struct io_sq_data *sqd;
|
struct io_sq_data *sqd;
|
||||||
struct fd f;
|
CLASS(fd, f)(p->wq_fd);
|
||||||
|
|
||||||
f = fdget(p->wq_fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return ERR_PTR(-ENXIO);
|
return ERR_PTR(-ENXIO);
|
||||||
if (!io_is_uring_fops(fd_file(f))) {
|
if (!io_is_uring_fops(fd_file(f)))
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
|
||||||
|
|
||||||
ctx_attach = fd_file(f)->private_data;
|
ctx_attach = fd_file(f)->private_data;
|
||||||
sqd = ctx_attach->sq_data;
|
sqd = ctx_attach->sq_data;
|
||||||
if (!sqd) {
|
if (!sqd)
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
if (sqd->task_tgid != current->tgid)
|
||||||
if (sqd->task_tgid != current->tgid) {
|
|
||||||
fdput(f);
|
|
||||||
return ERR_PTR(-EPERM);
|
return ERR_PTR(-EPERM);
|
||||||
}
|
|
||||||
|
|
||||||
refcount_inc(&sqd->refs);
|
refcount_inc(&sqd->refs);
|
||||||
fdput(f);
|
|
||||||
return sqd;
|
return sqd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,16 +409,11 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
|
|||||||
/* Retain compatibility with failing for an invalid attach attempt */
|
/* Retain compatibility with failing for an invalid attach attempt */
|
||||||
if ((ctx->flags & (IORING_SETUP_ATTACH_WQ | IORING_SETUP_SQPOLL)) ==
|
if ((ctx->flags & (IORING_SETUP_ATTACH_WQ | IORING_SETUP_SQPOLL)) ==
|
||||||
IORING_SETUP_ATTACH_WQ) {
|
IORING_SETUP_ATTACH_WQ) {
|
||||||
struct fd f;
|
CLASS(fd, f)(p->wq_fd);
|
||||||
|
if (fd_empty(f))
|
||||||
f = fdget(p->wq_fd);
|
|
||||||
if (!fd_file(f))
|
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
if (!io_is_uring_fops(fd_file(f))) {
|
if (!io_is_uring_fops(fd_file(f)))
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
if (ctx->flags & IORING_SETUP_SQPOLL) {
|
if (ctx->flags & IORING_SETUP_SQPOLL) {
|
||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
|
109
ipc/mqueue.c
109
ipc/mqueue.c
@ -1063,7 +1063,6 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
|
|||||||
size_t msg_len, unsigned int msg_prio,
|
size_t msg_len, unsigned int msg_prio,
|
||||||
struct timespec64 *ts)
|
struct timespec64 *ts)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct ext_wait_queue wait;
|
struct ext_wait_queue wait;
|
||||||
struct ext_wait_queue *receiver;
|
struct ext_wait_queue *receiver;
|
||||||
@ -1084,37 +1083,27 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
|
|||||||
|
|
||||||
audit_mq_sendrecv(mqdes, msg_len, msg_prio, ts);
|
audit_mq_sendrecv(mqdes, msg_len, msg_prio, ts);
|
||||||
|
|
||||||
f = fdget(mqdes);
|
CLASS(fd, f)(mqdes);
|
||||||
if (unlikely(!fd_file(f))) {
|
if (fd_empty(f))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
inode = file_inode(fd_file(f));
|
inode = file_inode(fd_file(f));
|
||||||
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) {
|
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
info = MQUEUE_I(inode);
|
info = MQUEUE_I(inode);
|
||||||
audit_file(fd_file(f));
|
audit_file(fd_file(f));
|
||||||
|
|
||||||
if (unlikely(!(fd_file(f)->f_mode & FMODE_WRITE))) {
|
if (unlikely(!(fd_file(f)->f_mode & FMODE_WRITE)))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(msg_len > info->attr.mq_msgsize)) {
|
if (unlikely(msg_len > info->attr.mq_msgsize))
|
||||||
ret = -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First try to allocate memory, before doing anything with
|
/* First try to allocate memory, before doing anything with
|
||||||
* existing queues. */
|
* existing queues. */
|
||||||
msg_ptr = load_msg(u_msg_ptr, msg_len);
|
msg_ptr = load_msg(u_msg_ptr, msg_len);
|
||||||
if (IS_ERR(msg_ptr)) {
|
if (IS_ERR(msg_ptr))
|
||||||
ret = PTR_ERR(msg_ptr);
|
return PTR_ERR(msg_ptr);
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
msg_ptr->m_ts = msg_len;
|
msg_ptr->m_ts = msg_len;
|
||||||
msg_ptr->m_type = msg_prio;
|
msg_ptr->m_type = msg_prio;
|
||||||
|
|
||||||
@ -1172,9 +1161,6 @@ out_unlock:
|
|||||||
out_free:
|
out_free:
|
||||||
if (ret)
|
if (ret)
|
||||||
free_msg(msg_ptr);
|
free_msg(msg_ptr);
|
||||||
out_fput:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1184,7 +1170,6 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
|
|||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct msg_msg *msg_ptr;
|
struct msg_msg *msg_ptr;
|
||||||
struct fd f;
|
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct mqueue_inode_info *info;
|
struct mqueue_inode_info *info;
|
||||||
struct ext_wait_queue wait;
|
struct ext_wait_queue wait;
|
||||||
@ -1198,30 +1183,22 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
|
|||||||
|
|
||||||
audit_mq_sendrecv(mqdes, msg_len, 0, ts);
|
audit_mq_sendrecv(mqdes, msg_len, 0, ts);
|
||||||
|
|
||||||
f = fdget(mqdes);
|
CLASS(fd, f)(mqdes);
|
||||||
if (unlikely(!fd_file(f))) {
|
if (fd_empty(f))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
inode = file_inode(fd_file(f));
|
inode = file_inode(fd_file(f));
|
||||||
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) {
|
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
info = MQUEUE_I(inode);
|
info = MQUEUE_I(inode);
|
||||||
audit_file(fd_file(f));
|
audit_file(fd_file(f));
|
||||||
|
|
||||||
if (unlikely(!(fd_file(f)->f_mode & FMODE_READ))) {
|
if (unlikely(!(fd_file(f)->f_mode & FMODE_READ)))
|
||||||
ret = -EBADF;
|
return -EBADF;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* checks if buffer is big enough */
|
/* checks if buffer is big enough */
|
||||||
if (unlikely(msg_len < info->attr.mq_msgsize)) {
|
if (unlikely(msg_len < info->attr.mq_msgsize))
|
||||||
ret = -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
goto out_fput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* msg_insert really wants us to have a valid, spare node struct so
|
* msg_insert really wants us to have a valid, spare node struct so
|
||||||
@ -1275,9 +1252,6 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
|
|||||||
}
|
}
|
||||||
free_msg(msg_ptr);
|
free_msg(msg_ptr);
|
||||||
}
|
}
|
||||||
out_fput:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1317,7 +1291,6 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
|
|||||||
static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
|
static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct fd f;
|
|
||||||
struct sock *sock;
|
struct sock *sock;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct mqueue_inode_info *info;
|
struct mqueue_inode_info *info;
|
||||||
@ -1347,39 +1320,31 @@ static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
|
|||||||
if (copy_from_user(nc->data,
|
if (copy_from_user(nc->data,
|
||||||
notification->sigev_value.sival_ptr,
|
notification->sigev_value.sival_ptr,
|
||||||
NOTIFY_COOKIE_LEN)) {
|
NOTIFY_COOKIE_LEN)) {
|
||||||
ret = -EFAULT;
|
kfree_skb(nc);
|
||||||
goto free_skb;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: add a header? */
|
/* TODO: add a header? */
|
||||||
skb_put(nc, NOTIFY_COOKIE_LEN);
|
skb_put(nc, NOTIFY_COOKIE_LEN);
|
||||||
/* and attach it to the socket */
|
/* and attach it to the socket */
|
||||||
retry:
|
retry:
|
||||||
f = fdget(notification->sigev_signo);
|
sock = netlink_getsockbyfd(notification->sigev_signo);
|
||||||
if (!fd_file(f)) {
|
|
||||||
ret = -EBADF;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
sock = netlink_getsockbyfilp(fd_file(f));
|
|
||||||
fdput(f);
|
|
||||||
if (IS_ERR(sock)) {
|
if (IS_ERR(sock)) {
|
||||||
ret = PTR_ERR(sock);
|
kfree_skb(nc);
|
||||||
goto free_skb;
|
return PTR_ERR(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
timeo = MAX_SCHEDULE_TIMEOUT;
|
timeo = MAX_SCHEDULE_TIMEOUT;
|
||||||
ret = netlink_attachskb(sock, nc, &timeo, NULL);
|
ret = netlink_attachskb(sock, nc, &timeo, NULL);
|
||||||
if (ret == 1) {
|
if (ret == 1)
|
||||||
sock = NULL;
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fdget(mqdes);
|
CLASS(fd, f)(mqdes);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1387,7 +1352,7 @@ retry:
|
|||||||
inode = file_inode(fd_file(f));
|
inode = file_inode(fd_file(f));
|
||||||
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) {
|
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out_fput;
|
goto out;
|
||||||
}
|
}
|
||||||
info = MQUEUE_I(inode);
|
info = MQUEUE_I(inode);
|
||||||
|
|
||||||
@ -1426,15 +1391,9 @@ retry:
|
|||||||
inode_set_atime_to_ts(inode, inode_set_ctime_current(inode));
|
inode_set_atime_to_ts(inode, inode_set_ctime_current(inode));
|
||||||
}
|
}
|
||||||
spin_unlock(&info->lock);
|
spin_unlock(&info->lock);
|
||||||
out_fput:
|
|
||||||
fdput(f);
|
|
||||||
out:
|
out:
|
||||||
if (sock)
|
if (sock)
|
||||||
netlink_detachskb(sock, nc);
|
netlink_detachskb(sock, nc);
|
||||||
else
|
|
||||||
free_skb:
|
|
||||||
dev_kfree_skb(nc);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1452,21 +1411,18 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
|
|||||||
|
|
||||||
static int do_mq_getsetattr(int mqdes, struct mq_attr *new, struct mq_attr *old)
|
static int do_mq_getsetattr(int mqdes, struct mq_attr *new, struct mq_attr *old)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct mqueue_inode_info *info;
|
struct mqueue_inode_info *info;
|
||||||
|
|
||||||
if (new && (new->mq_flags & (~O_NONBLOCK)))
|
if (new && (new->mq_flags & (~O_NONBLOCK)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(mqdes);
|
CLASS(fd, f)(mqdes);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) {
|
if (unlikely(fd_file(f)->f_op != &mqueue_file_operations))
|
||||||
fdput(f);
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
|
||||||
|
|
||||||
inode = file_inode(fd_file(f));
|
inode = file_inode(fd_file(f));
|
||||||
info = MQUEUE_I(inode);
|
info = MQUEUE_I(inode);
|
||||||
@ -1490,7 +1446,6 @@ static int do_mq_getsetattr(int mqdes, struct mq_attr *new, struct mq_attr *old)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&info->lock);
|
spin_unlock(&info->lock);
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6476,7 +6476,6 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
|
|||||||
struct cgroup *dst_cgrp = NULL;
|
struct cgroup *dst_cgrp = NULL;
|
||||||
struct css_set *cset;
|
struct css_set *cset;
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct file *f;
|
|
||||||
|
|
||||||
if (kargs->flags & CLONE_INTO_CGROUP)
|
if (kargs->flags & CLONE_INTO_CGROUP)
|
||||||
cgroup_lock();
|
cgroup_lock();
|
||||||
@ -6493,14 +6492,14 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fget_raw(kargs->cgroup);
|
CLASS(fd_raw, f)(kargs->cgroup);
|
||||||
if (!f) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
sb = f->f_path.dentry->d_sb;
|
sb = fd_file(f)->f_path.dentry->d_sb;
|
||||||
|
|
||||||
dst_cgrp = cgroup_get_from_file(f);
|
dst_cgrp = cgroup_get_from_file(fd_file(f));
|
||||||
if (IS_ERR(dst_cgrp)) {
|
if (IS_ERR(dst_cgrp)) {
|
||||||
ret = PTR_ERR(dst_cgrp);
|
ret = PTR_ERR(dst_cgrp);
|
||||||
dst_cgrp = NULL;
|
dst_cgrp = NULL;
|
||||||
@ -6548,15 +6547,12 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
put_css_set(cset);
|
put_css_set(cset);
|
||||||
fput(f);
|
|
||||||
kargs->cgrp = dst_cgrp;
|
kargs->cgrp = dst_cgrp;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
cgroup_threadgroup_change_end(current);
|
cgroup_threadgroup_change_end(current);
|
||||||
cgroup_unlock();
|
cgroup_unlock();
|
||||||
if (f)
|
|
||||||
fput(f);
|
|
||||||
if (dst_cgrp)
|
if (dst_cgrp)
|
||||||
cgroup_put(dst_cgrp);
|
cgroup_put(dst_cgrp);
|
||||||
put_css_set(cset);
|
put_css_set(cset);
|
||||||
@ -6966,14 +6962,11 @@ EXPORT_SYMBOL_GPL(cgroup_get_from_path);
|
|||||||
*/
|
*/
|
||||||
struct cgroup *cgroup_v1v2_get_from_fd(int fd)
|
struct cgroup *cgroup_v1v2_get_from_fd(int fd)
|
||||||
{
|
{
|
||||||
struct cgroup *cgrp;
|
CLASS(fd_raw, f)(fd);
|
||||||
struct fd f = fdget_raw(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
cgrp = cgroup_v1v2_get_from_file(fd_file(f));
|
return cgroup_v1v2_get_from_file(fd_file(f));
|
||||||
fdput(f);
|
|
||||||
return cgrp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -966,22 +966,20 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
|
|||||||
{
|
{
|
||||||
struct perf_cgroup *cgrp;
|
struct perf_cgroup *cgrp;
|
||||||
struct cgroup_subsys_state *css;
|
struct cgroup_subsys_state *css;
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
css = css_tryget_online_from_dir(fd_file(f)->f_path.dentry,
|
css = css_tryget_online_from_dir(fd_file(f)->f_path.dentry,
|
||||||
&perf_event_cgrp_subsys);
|
&perf_event_cgrp_subsys);
|
||||||
if (IS_ERR(css)) {
|
if (IS_ERR(css))
|
||||||
ret = PTR_ERR(css);
|
return PTR_ERR(css);
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = perf_cgroup_ensure_storage(event, css);
|
ret = perf_cgroup_ensure_storage(event, css);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
return ret;
|
||||||
|
|
||||||
cgrp = container_of(css, struct perf_cgroup, css);
|
cgrp = container_of(css, struct perf_cgroup, css);
|
||||||
event->cgrp = cgrp;
|
event->cgrp = cgrp;
|
||||||
@ -995,8 +993,6 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
|
|||||||
perf_detach_cgroup(event);
|
perf_detach_cgroup(event);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5998,18 +5994,9 @@ EXPORT_SYMBOL_GPL(perf_event_period);
|
|||||||
|
|
||||||
static const struct file_operations perf_fops;
|
static const struct file_operations perf_fops;
|
||||||
|
|
||||||
static inline int perf_fget_light(int fd, struct fd *p)
|
static inline bool is_perf_file(struct fd f)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
return !fd_empty(f) && fd_file(f)->f_op == &perf_fops;
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
if (fd_file(f)->f_op != &perf_fops) {
|
|
||||||
fdput(f);
|
|
||||||
return -EBADF;
|
|
||||||
}
|
|
||||||
*p = f;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_event_set_output(struct perf_event *event,
|
static int perf_event_set_output(struct perf_event *event,
|
||||||
@ -6057,20 +6044,14 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
|
|||||||
|
|
||||||
case PERF_EVENT_IOC_SET_OUTPUT:
|
case PERF_EVENT_IOC_SET_OUTPUT:
|
||||||
{
|
{
|
||||||
int ret;
|
CLASS(fd, output)(arg); // arg == -1 => empty
|
||||||
|
struct perf_event *output_event = NULL;
|
||||||
if (arg != -1) {
|
if (arg != -1) {
|
||||||
struct perf_event *output_event;
|
if (!is_perf_file(output))
|
||||||
struct fd output;
|
return -EBADF;
|
||||||
ret = perf_fget_light(arg, &output);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
output_event = fd_file(output)->private_data;
|
output_event = fd_file(output)->private_data;
|
||||||
ret = perf_event_set_output(event, output_event);
|
|
||||||
fdput(output);
|
|
||||||
} else {
|
|
||||||
ret = perf_event_set_output(event, NULL);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return perf_event_set_output(event, output_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
case PERF_EVENT_IOC_SET_FILTER:
|
case PERF_EVENT_IOC_SET_FILTER:
|
||||||
@ -12664,7 +12645,6 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
struct perf_event_attr attr;
|
struct perf_event_attr attr;
|
||||||
struct perf_event_context *ctx;
|
struct perf_event_context *ctx;
|
||||||
struct file *event_file = NULL;
|
struct file *event_file = NULL;
|
||||||
struct fd group = EMPTY_FD;
|
|
||||||
struct task_struct *task = NULL;
|
struct task_struct *task = NULL;
|
||||||
struct pmu *pmu;
|
struct pmu *pmu;
|
||||||
int event_fd;
|
int event_fd;
|
||||||
@ -12735,10 +12715,12 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
if (event_fd < 0)
|
if (event_fd < 0)
|
||||||
return event_fd;
|
return event_fd;
|
||||||
|
|
||||||
|
CLASS(fd, group)(group_fd); // group_fd == -1 => empty
|
||||||
if (group_fd != -1) {
|
if (group_fd != -1) {
|
||||||
err = perf_fget_light(group_fd, &group);
|
if (!is_perf_file(group)) {
|
||||||
if (err)
|
err = -EBADF;
|
||||||
goto err_fd;
|
goto err_fd;
|
||||||
|
}
|
||||||
group_leader = fd_file(group)->private_data;
|
group_leader = fd_file(group)->private_data;
|
||||||
if (flags & PERF_FLAG_FD_OUTPUT)
|
if (flags & PERF_FLAG_FD_OUTPUT)
|
||||||
output_event = group_leader;
|
output_event = group_leader;
|
||||||
@ -12750,7 +12732,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
task = find_lively_task_by_vpid(pid);
|
task = find_lively_task_by_vpid(pid);
|
||||||
if (IS_ERR(task)) {
|
if (IS_ERR(task)) {
|
||||||
err = PTR_ERR(task);
|
err = PTR_ERR(task);
|
||||||
goto err_group_fd;
|
goto err_fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13017,12 +12999,11 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
mutex_unlock(¤t->perf_event_mutex);
|
mutex_unlock(¤t->perf_event_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop the reference on the group_event after placing the
|
* File reference in group guarantees that group_leader has been
|
||||||
* new event on the sibling_list. This ensures destruction
|
* kept alive until we place the new event on the sibling_list.
|
||||||
* of the group leader will find the pointer to itself in
|
* This ensures destruction of the group leader will find
|
||||||
* perf_group_detach().
|
* the pointer to itself in perf_group_detach().
|
||||||
*/
|
*/
|
||||||
fdput(group);
|
|
||||||
fd_install(event_fd, event_file);
|
fd_install(event_fd, event_file);
|
||||||
return event_fd;
|
return event_fd;
|
||||||
|
|
||||||
@ -13041,8 +13022,6 @@ err_alloc:
|
|||||||
err_task:
|
err_task:
|
||||||
if (task)
|
if (task)
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
err_group_fd:
|
|
||||||
fdput(group);
|
|
||||||
err_fd:
|
err_fd:
|
||||||
put_unused_fd(event_fd);
|
put_unused_fd(event_fd);
|
||||||
return err;
|
return err;
|
||||||
|
@ -3202,7 +3202,7 @@ static int idempotent_init_module(struct file *f, const char __user * uargs, int
|
|||||||
{
|
{
|
||||||
struct idempotent idem;
|
struct idempotent idem;
|
||||||
|
|
||||||
if (!f || !(f->f_mode & FMODE_READ))
|
if (!(f->f_mode & FMODE_READ))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
/* Are we the winners of the race and get to do this? */
|
/* Are we the winners of the race and get to do this? */
|
||||||
@ -3219,10 +3219,7 @@ static int idempotent_init_module(struct file *f, const char __user * uargs, int
|
|||||||
|
|
||||||
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|
||||||
{
|
{
|
||||||
int err;
|
int err = may_init_module();
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
err = may_init_module();
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -3233,10 +3230,10 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|
|||||||
|MODULE_INIT_COMPRESSED_FILE))
|
|MODULE_INIT_COMPRESSED_FILE))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
err = idempotent_init_module(fd_file(f), uargs, flags);
|
if (fd_empty(f))
|
||||||
fdput(f);
|
return -EBADF;
|
||||||
return err;
|
return idempotent_init_module(fd_file(f), uargs, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
|
/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
|
||||||
|
@ -545,12 +545,12 @@ static void commit_nsset(struct nsset *nsset)
|
|||||||
|
|
||||||
SYSCALL_DEFINE2(setns, int, fd, int, flags)
|
SYSCALL_DEFINE2(setns, int, fd, int, flags)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct ns_common *ns = NULL;
|
struct ns_common *ns = NULL;
|
||||||
struct nsset nsset = {};
|
struct nsset nsset = {};
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (proc_ns_file(fd_file(f))) {
|
if (proc_ns_file(fd_file(f))) {
|
||||||
@ -580,7 +580,6 @@ SYSCALL_DEFINE2(setns, int, fd, int, flags)
|
|||||||
}
|
}
|
||||||
put_nsset(&nsset);
|
put_nsset(&nsset);
|
||||||
out:
|
out:
|
||||||
fdput(f);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
kernel/pid.c
20
kernel/pid.c
@ -536,11 +536,10 @@ EXPORT_SYMBOL_GPL(find_ge_pid);
|
|||||||
|
|
||||||
struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)
|
struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd, f)(fd);
|
||||||
struct pid *pid;
|
struct pid *pid;
|
||||||
|
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
pid = pidfd_pid(fd_file(f));
|
pid = pidfd_pid(fd_file(f));
|
||||||
@ -548,8 +547,6 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)
|
|||||||
get_pid(pid);
|
get_pid(pid);
|
||||||
*flags = fd_file(f)->f_flags;
|
*flags = fd_file(f)->f_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,23 +744,18 @@ SYSCALL_DEFINE3(pidfd_getfd, int, pidfd, int, fd,
|
|||||||
unsigned int, flags)
|
unsigned int, flags)
|
||||||
{
|
{
|
||||||
struct pid *pid;
|
struct pid *pid;
|
||||||
struct fd f;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* flags is currently unused - make sure it's unset */
|
/* flags is currently unused - make sure it's unset */
|
||||||
if (flags)
|
if (flags)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(pidfd);
|
CLASS(fd, f)(pidfd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
pid = pidfd_pid(fd_file(f));
|
pid = pidfd_pid(fd_file(f));
|
||||||
if (IS_ERR(pid))
|
if (IS_ERR(pid))
|
||||||
ret = PTR_ERR(pid);
|
return PTR_ERR(pid);
|
||||||
else
|
|
||||||
ret = pidfd_getfd(pid, fd);
|
|
||||||
|
|
||||||
fdput(f);
|
return pidfd_getfd(pid, fd);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
@ -3909,7 +3909,6 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
|
|||||||
siginfo_t __user *, info, unsigned int, flags)
|
siginfo_t __user *, info, unsigned int, flags)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct fd f;
|
|
||||||
struct pid *pid;
|
struct pid *pid;
|
||||||
kernel_siginfo_t kinfo;
|
kernel_siginfo_t kinfo;
|
||||||
enum pid_type type;
|
enum pid_type type;
|
||||||
@ -3922,20 +3921,17 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
|
|||||||
if (hweight32(flags & PIDFD_SEND_SIGNAL_FLAGS) > 1)
|
if (hweight32(flags & PIDFD_SEND_SIGNAL_FLAGS) > 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f = fdget(pidfd);
|
CLASS(fd, f)(pidfd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
/* Is this a pidfd? */
|
/* Is this a pidfd? */
|
||||||
pid = pidfd_to_pid(fd_file(f));
|
pid = pidfd_to_pid(fd_file(f));
|
||||||
if (IS_ERR(pid)) {
|
if (IS_ERR(pid))
|
||||||
ret = PTR_ERR(pid);
|
return PTR_ERR(pid);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = -EINVAL;
|
|
||||||
if (!access_pidfd_pidns(pid))
|
if (!access_pidfd_pidns(pid))
|
||||||
goto err;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (flags) {
|
switch (flags) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -3959,28 +3955,23 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, pidfd, int, sig,
|
|||||||
if (info) {
|
if (info) {
|
||||||
ret = copy_siginfo_from_user_any(&kinfo, info);
|
ret = copy_siginfo_from_user_any(&kinfo, info);
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
goto err;
|
return ret;
|
||||||
|
|
||||||
ret = -EINVAL;
|
|
||||||
if (unlikely(sig != kinfo.si_signo))
|
if (unlikely(sig != kinfo.si_signo))
|
||||||
goto err;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Only allow sending arbitrary signals to yourself. */
|
/* Only allow sending arbitrary signals to yourself. */
|
||||||
ret = -EPERM;
|
|
||||||
if ((task_pid(current) != pid || type > PIDTYPE_TGID) &&
|
if ((task_pid(current) != pid || type > PIDTYPE_TGID) &&
|
||||||
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
|
(kinfo.si_code >= 0 || kinfo.si_code == SI_TKILL))
|
||||||
goto err;
|
return -EPERM;
|
||||||
} else {
|
} else {
|
||||||
prepare_kill_siginfo(sig, &kinfo, type);
|
prepare_kill_siginfo(sig, &kinfo, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == PIDTYPE_PGID)
|
if (type == PIDTYPE_PGID)
|
||||||
ret = kill_pgrp_info(sig, &kinfo, pid);
|
return kill_pgrp_info(sig, &kinfo, pid);
|
||||||
else
|
else
|
||||||
ret = kill_pid_info_type(sig, &kinfo, pid, type);
|
return kill_pid_info_type(sig, &kinfo, pid, type);
|
||||||
err:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
15
kernel/sys.c
15
kernel/sys.c
@ -1911,12 +1911,11 @@ SYSCALL_DEFINE1(umask, int, mask)
|
|||||||
|
|
||||||
static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
|
static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
|
||||||
{
|
{
|
||||||
struct fd exe;
|
CLASS(fd, exe)(fd);
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
exe = fdget(fd);
|
if (fd_empty(exe))
|
||||||
if (!fd_file(exe))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
inode = file_inode(fd_file(exe));
|
inode = file_inode(fd_file(exe));
|
||||||
@ -1926,18 +1925,14 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
|
|||||||
* sure that this one is executable as well, to avoid breaking an
|
* sure that this one is executable as well, to avoid breaking an
|
||||||
* overall picture.
|
* overall picture.
|
||||||
*/
|
*/
|
||||||
err = -EACCES;
|
|
||||||
if (!S_ISREG(inode->i_mode) || path_noexec(&fd_file(exe)->f_path))
|
if (!S_ISREG(inode->i_mode) || path_noexec(&fd_file(exe)->f_path))
|
||||||
goto exit;
|
return -EACCES;
|
||||||
|
|
||||||
err = file_permission(fd_file(exe), MAY_EXEC);
|
err = file_permission(fd_file(exe), MAY_EXEC);
|
||||||
if (err)
|
if (err)
|
||||||
goto exit;
|
return err;
|
||||||
|
|
||||||
err = replace_mm_exe_file(mm, fd_file(exe));
|
return replace_mm_exe_file(mm, fd_file(exe));
|
||||||
exit:
|
|
||||||
fdput(exe);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -411,15 +411,14 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
|
|||||||
struct nlattr *na;
|
struct nlattr *na;
|
||||||
size_t size;
|
size_t size;
|
||||||
u32 fd;
|
u32 fd;
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
na = info->attrs[CGROUPSTATS_CMD_ATTR_FD];
|
na = info->attrs[CGROUPSTATS_CMD_ATTR_FD];
|
||||||
if (!na)
|
if (!na)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
|
fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
size = nla_total_size(sizeof(struct cgroupstats));
|
size = nla_total_size(sizeof(struct cgroupstats));
|
||||||
@ -427,14 +426,13 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
|
|||||||
rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
|
rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
|
||||||
size);
|
size);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto err;
|
return rc;
|
||||||
|
|
||||||
na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
|
na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
|
||||||
sizeof(struct cgroupstats));
|
sizeof(struct cgroupstats));
|
||||||
if (na == NULL) {
|
if (na == NULL) {
|
||||||
nlmsg_free(rep_skb);
|
nlmsg_free(rep_skb);
|
||||||
rc = -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stats = nla_data(na);
|
stats = nla_data(na);
|
||||||
@ -443,14 +441,10 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
|
|||||||
rc = cgroupstats_build(stats, fd_file(f)->f_path.dentry);
|
rc = cgroupstats_build(stats, fd_file(f)->f_path.dentry);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
nlmsg_free(rep_skb);
|
nlmsg_free(rep_skb);
|
||||||
goto err;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = send_reply(rep_skb, info);
|
return send_reply(rep_skb, info);
|
||||||
|
|
||||||
err:
|
|
||||||
fdput(f);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_attr_register_cpumask(struct genl_info *info)
|
static int cmd_attr_register_cpumask(struct genl_info *info)
|
||||||
|
@ -663,16 +663,14 @@ struct watch_queue *get_watch_queue(int fd)
|
|||||||
{
|
{
|
||||||
struct pipe_inode_info *pipe;
|
struct pipe_inode_info *pipe;
|
||||||
struct watch_queue *wqueue = ERR_PTR(-EINVAL);
|
struct watch_queue *wqueue = ERR_PTR(-EINVAL);
|
||||||
struct fd f;
|
CLASS(fd, f)(fd);
|
||||||
|
|
||||||
f = fdget(fd);
|
if (!fd_empty(f)) {
|
||||||
if (fd_file(f)) {
|
|
||||||
pipe = get_pipe_info(fd_file(f), false);
|
pipe = get_pipe_info(fd_file(f), false);
|
||||||
if (pipe && pipe->watch_queue) {
|
if (pipe && pipe->watch_queue) {
|
||||||
wqueue = pipe->watch_queue;
|
wqueue = pipe->watch_queue;
|
||||||
kref_get(&wqueue->usage);
|
kref_get(&wqueue->usage);
|
||||||
}
|
}
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return wqueue;
|
return wqueue;
|
||||||
|
10
mm/fadvise.c
10
mm/fadvise.c
@ -190,16 +190,12 @@ EXPORT_SYMBOL(vfs_fadvise);
|
|||||||
|
|
||||||
int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = vfs_fadvise(fd_file(f), offset, len, advice);
|
return vfs_fadvise(fd_file(f), offset, len, advice);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
|
SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
|
||||||
|
17
mm/filemap.c
17
mm/filemap.c
@ -4423,31 +4423,25 @@ SYSCALL_DEFINE4(cachestat, unsigned int, fd,
|
|||||||
struct cachestat_range __user *, cstat_range,
|
struct cachestat_range __user *, cstat_range,
|
||||||
struct cachestat __user *, cstat, unsigned int, flags)
|
struct cachestat __user *, cstat, unsigned int, flags)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct address_space *mapping;
|
struct address_space *mapping;
|
||||||
struct cachestat_range csr;
|
struct cachestat_range csr;
|
||||||
struct cachestat cs;
|
struct cachestat cs;
|
||||||
pgoff_t first_index, last_index;
|
pgoff_t first_index, last_index;
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (copy_from_user(&csr, cstat_range,
|
if (copy_from_user(&csr, cstat_range,
|
||||||
sizeof(struct cachestat_range))) {
|
sizeof(struct cachestat_range)))
|
||||||
fdput(f);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
/* hugetlbfs is not supported */
|
/* hugetlbfs is not supported */
|
||||||
if (is_file_hugepages(fd_file(f))) {
|
if (is_file_hugepages(fd_file(f)))
|
||||||
fdput(f);
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
|
||||||
|
|
||||||
if (flags != 0) {
|
if (flags != 0)
|
||||||
fdput(f);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
first_index = csr.off >> PAGE_SHIFT;
|
first_index = csr.off >> PAGE_SHIFT;
|
||||||
last_index =
|
last_index =
|
||||||
@ -4455,7 +4449,6 @@ SYSCALL_DEFINE4(cachestat, unsigned int, fd,
|
|||||||
memset(&cs, 0, sizeof(struct cachestat));
|
memset(&cs, 0, sizeof(struct cachestat));
|
||||||
mapping = fd_file(f)->f_mapping;
|
mapping = fd_file(f)->f_mapping;
|
||||||
filemap_cachestat(mapping, first_index, last_index, &cs);
|
filemap_cachestat(mapping, first_index, last_index, &cs);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
if (copy_to_user(cstat, &cs, sizeof(struct cachestat)))
|
if (copy_to_user(cstat, &cs, sizeof(struct cachestat)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -1936,8 +1936,6 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
struct mem_cgroup_event *event;
|
struct mem_cgroup_event *event;
|
||||||
struct cgroup_subsys_state *cfile_css;
|
struct cgroup_subsys_state *cfile_css;
|
||||||
unsigned int efd, cfd;
|
unsigned int efd, cfd;
|
||||||
struct fd efile;
|
|
||||||
struct fd cfile;
|
|
||||||
struct dentry *cdentry;
|
struct dentry *cdentry;
|
||||||
const char *name;
|
const char *name;
|
||||||
char *endp;
|
char *endp;
|
||||||
@ -1961,6 +1959,12 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
else
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
CLASS(fd, efile)(efd);
|
||||||
|
if (fd_empty(efile))
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
CLASS(fd, cfile)(cfd);
|
||||||
|
|
||||||
event = kzalloc(sizeof(*event), GFP_KERNEL);
|
event = kzalloc(sizeof(*event), GFP_KERNEL);
|
||||||
if (!event)
|
if (!event)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -1971,20 +1975,13 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
init_waitqueue_func_entry(&event->wait, memcg_event_wake);
|
init_waitqueue_func_entry(&event->wait, memcg_event_wake);
|
||||||
INIT_WORK(&event->remove, memcg_event_remove);
|
INIT_WORK(&event->remove, memcg_event_remove);
|
||||||
|
|
||||||
efile = fdget(efd);
|
|
||||||
if (!fd_file(efile)) {
|
|
||||||
ret = -EBADF;
|
|
||||||
goto out_kfree;
|
|
||||||
}
|
|
||||||
|
|
||||||
event->eventfd = eventfd_ctx_fileget(fd_file(efile));
|
event->eventfd = eventfd_ctx_fileget(fd_file(efile));
|
||||||
if (IS_ERR(event->eventfd)) {
|
if (IS_ERR(event->eventfd)) {
|
||||||
ret = PTR_ERR(event->eventfd);
|
ret = PTR_ERR(event->eventfd);
|
||||||
goto out_put_efile;
|
goto out_kfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfile = fdget(cfd);
|
if (fd_empty(cfile)) {
|
||||||
if (!fd_file(cfile)) {
|
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out_put_eventfd;
|
goto out_put_eventfd;
|
||||||
}
|
}
|
||||||
@ -1993,7 +1990,7 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
/* AV: shouldn't we check that it's been opened for read instead? */
|
/* AV: shouldn't we check that it's been opened for read instead? */
|
||||||
ret = file_permission(fd_file(cfile), MAY_READ);
|
ret = file_permission(fd_file(cfile), MAY_READ);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_put_cfile;
|
goto out_put_eventfd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The control file must be a regular cgroup1 file. As a regular cgroup
|
* The control file must be a regular cgroup1 file. As a regular cgroup
|
||||||
@ -2002,7 +1999,7 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
cdentry = fd_file(cfile)->f_path.dentry;
|
cdentry = fd_file(cfile)->f_path.dentry;
|
||||||
if (cdentry->d_sb->s_type != &cgroup_fs_type || !d_is_reg(cdentry)) {
|
if (cdentry->d_sb->s_type != &cgroup_fs_type || !d_is_reg(cdentry)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_put_cfile;
|
goto out_put_eventfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2035,7 +2032,7 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
event->unregister_event = memsw_cgroup_usage_unregister_event;
|
event->unregister_event = memsw_cgroup_usage_unregister_event;
|
||||||
} else {
|
} else {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_put_cfile;
|
goto out_put_eventfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2047,11 +2044,9 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
&memory_cgrp_subsys);
|
&memory_cgrp_subsys);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (IS_ERR(cfile_css))
|
if (IS_ERR(cfile_css))
|
||||||
goto out_put_cfile;
|
goto out_put_eventfd;
|
||||||
if (cfile_css != css) {
|
if (cfile_css != css)
|
||||||
css_put(cfile_css);
|
goto out_put_css;
|
||||||
goto out_put_cfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = event->register_event(memcg, event->eventfd, buf);
|
ret = event->register_event(memcg, event->eventfd, buf);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -2062,23 +2057,14 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
|
|||||||
spin_lock_irq(&memcg->event_list_lock);
|
spin_lock_irq(&memcg->event_list_lock);
|
||||||
list_add(&event->list, &memcg->event_list);
|
list_add(&event->list, &memcg->event_list);
|
||||||
spin_unlock_irq(&memcg->event_list_lock);
|
spin_unlock_irq(&memcg->event_list_lock);
|
||||||
|
|
||||||
fdput(cfile);
|
|
||||||
fdput(efile);
|
|
||||||
|
|
||||||
return nbytes;
|
return nbytes;
|
||||||
|
|
||||||
out_put_css:
|
out_put_css:
|
||||||
css_put(css);
|
css_put(cfile_css);
|
||||||
out_put_cfile:
|
|
||||||
fdput(cfile);
|
|
||||||
out_put_eventfd:
|
out_put_eventfd:
|
||||||
eventfd_ctx_put(event->eventfd);
|
eventfd_ctx_put(event->eventfd);
|
||||||
out_put_efile:
|
|
||||||
fdput(efile);
|
|
||||||
out_kfree:
|
out_kfree:
|
||||||
kfree(event);
|
kfree(event);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,29 +673,22 @@ EXPORT_SYMBOL_GPL(page_cache_async_ra);
|
|||||||
|
|
||||||
ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
|
ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
CLASS(fd, f)(fd);
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
ret = -EBADF;
|
if (fd_empty(f) || !(fd_file(f)->f_mode & FMODE_READ))
|
||||||
f = fdget(fd);
|
return -EBADF;
|
||||||
if (!fd_file(f) || !(fd_file(f)->f_mode & FMODE_READ))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The readahead() syscall is intended to run only on files
|
* The readahead() syscall is intended to run only on files
|
||||||
* that can execute readahead. If readahead is not possible
|
* that can execute readahead. If readahead is not possible
|
||||||
* on this file, then we must return -EINVAL.
|
* on this file, then we must return -EINVAL.
|
||||||
*/
|
*/
|
||||||
ret = -EINVAL;
|
|
||||||
if (!fd_file(f)->f_mapping || !fd_file(f)->f_mapping->a_ops ||
|
if (!fd_file(f)->f_mapping || !fd_file(f)->f_mapping->a_ops ||
|
||||||
(!S_ISREG(file_inode(fd_file(f))->i_mode) &&
|
(!S_ISREG(file_inode(fd_file(f))->i_mode) &&
|
||||||
!S_ISBLK(file_inode(fd_file(f))->i_mode)))
|
!S_ISBLK(file_inode(fd_file(f))->i_mode)))
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = vfs_fadvise(fd_file(f), offset, count, POSIX_FADV_WILLNEED);
|
return vfs_fadvise(fd_file(f), offset, count, POSIX_FADV_WILLNEED);
|
||||||
out:
|
|
||||||
fdput(f);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)
|
SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)
|
||||||
|
@ -694,20 +694,18 @@ EXPORT_SYMBOL_GPL(get_net_ns);
|
|||||||
|
|
||||||
struct net *get_net_ns_by_fd(int fd)
|
struct net *get_net_ns_by_fd(int fd)
|
||||||
{
|
{
|
||||||
struct fd f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
struct net *net = ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
if (proc_ns_file(fd_file(f))) {
|
if (proc_ns_file(fd_file(f))) {
|
||||||
struct ns_common *ns = get_proc_ns(file_inode(fd_file(f)));
|
struct ns_common *ns = get_proc_ns(file_inode(fd_file(f)));
|
||||||
if (ns->ops == &netns_operations)
|
if (ns->ops == &netns_operations)
|
||||||
net = get_net(container_of(ns, struct net, ns));
|
return get_net(container_of(ns, struct net, ns));
|
||||||
}
|
}
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return net;
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(get_net_ns_by_fd);
|
EXPORT_SYMBOL_GPL(get_net_ns_by_fd);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1165,11 +1165,16 @@ static struct sock *netlink_getsockbyportid(struct sock *ssk, u32 portid)
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sock *netlink_getsockbyfilp(struct file *filp)
|
struct sock *netlink_getsockbyfd(int fd)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(filp);
|
CLASS(fd, f)(fd);
|
||||||
|
struct inode *inode;
|
||||||
struct sock *sock;
|
struct sock *sock;
|
||||||
|
|
||||||
|
if (fd_empty(f))
|
||||||
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
|
inode = file_inode(fd_file(f));
|
||||||
if (!S_ISSOCK(inode->i_mode))
|
if (!S_ISSOCK(inode->i_mode))
|
||||||
return ERR_PTR(-ENOTSOCK);
|
return ERR_PTR(-ENOTSOCK);
|
||||||
|
|
||||||
|
301
net/socket.c
301
net/socket.c
@ -509,7 +509,7 @@ static int sock_map_fd(struct socket *sock, int flags)
|
|||||||
|
|
||||||
struct socket *sock_from_file(struct file *file)
|
struct socket *sock_from_file(struct file *file)
|
||||||
{
|
{
|
||||||
if (file->f_op == &socket_file_ops)
|
if (likely(file->f_op == &socket_file_ops))
|
||||||
return file->private_data; /* set in sock_alloc_file */
|
return file->private_data; /* set in sock_alloc_file */
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -549,24 +549,6 @@ struct socket *sockfd_lookup(int fd, int *err)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sockfd_lookup);
|
EXPORT_SYMBOL(sockfd_lookup);
|
||||||
|
|
||||||
static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
|
|
||||||
{
|
|
||||||
struct fd f = fdget(fd);
|
|
||||||
struct socket *sock;
|
|
||||||
|
|
||||||
*err = -EBADF;
|
|
||||||
if (fd_file(f)) {
|
|
||||||
sock = sock_from_file(fd_file(f));
|
|
||||||
if (likely(sock)) {
|
|
||||||
*fput_needed = f.word & FDPUT_FPUT;
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
*err = -ENOTSOCK;
|
|
||||||
fdput(f);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
|
static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
@ -1858,16 +1840,20 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
|
|||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
struct sockaddr_storage address;
|
struct sockaddr_storage address;
|
||||||
int err, fput_needed;
|
CLASS(fd, f)(fd);
|
||||||
|
int err;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (sock) {
|
return -EBADF;
|
||||||
err = move_addr_to_kernel(umyaddr, addrlen, &address);
|
sock = sock_from_file(fd_file(f));
|
||||||
if (!err)
|
if (unlikely(!sock))
|
||||||
err = __sys_bind_socket(sock, &address, addrlen);
|
return -ENOTSOCK;
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
}
|
err = move_addr_to_kernel(umyaddr, addrlen, &address);
|
||||||
return err;
|
if (unlikely(err))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return __sys_bind_socket(sock, &address, addrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
|
SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
|
||||||
@ -1896,15 +1882,16 @@ int __sys_listen_socket(struct socket *sock, int backlog)
|
|||||||
|
|
||||||
int __sys_listen(int fd, int backlog)
|
int __sys_listen(int fd, int backlog)
|
||||||
{
|
{
|
||||||
|
CLASS(fd, f)(fd);
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
int err, fput_needed;
|
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (sock) {
|
return -EBADF;
|
||||||
err = __sys_listen_socket(sock, backlog);
|
sock = sock_from_file(fd_file(f));
|
||||||
fput_light(sock->file, fput_needed);
|
if (unlikely(!sock))
|
||||||
}
|
return -ENOTSOCK;
|
||||||
return err;
|
|
||||||
|
return __sys_listen_socket(sock, backlog);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE2(listen, int, fd, int, backlog)
|
SYSCALL_DEFINE2(listen, int, fd, int, backlog)
|
||||||
@ -2014,17 +2001,12 @@ static int __sys_accept4_file(struct file *file, struct sockaddr __user *upeer_s
|
|||||||
int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
|
int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
|
||||||
int __user *upeer_addrlen, int flags)
|
int __user *upeer_addrlen, int flags)
|
||||||
{
|
{
|
||||||
int ret = -EBADF;
|
CLASS(fd, f)(fd);
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (fd_file(f)) {
|
return -EBADF;
|
||||||
ret = __sys_accept4_file(fd_file(f), upeer_sockaddr,
|
return __sys_accept4_file(fd_file(f), upeer_sockaddr,
|
||||||
upeer_addrlen, flags);
|
upeer_addrlen, flags);
|
||||||
fdput(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
|
SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
|
||||||
@ -2076,20 +2058,18 @@ out:
|
|||||||
|
|
||||||
int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
|
int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
|
||||||
{
|
{
|
||||||
int ret = -EBADF;
|
struct sockaddr_storage address;
|
||||||
struct fd f;
|
CLASS(fd, f)(fd);
|
||||||
|
int ret;
|
||||||
|
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (fd_file(f)) {
|
return -EBADF;
|
||||||
struct sockaddr_storage address;
|
|
||||||
|
|
||||||
ret = move_addr_to_kernel(uservaddr, addrlen, &address);
|
ret = move_addr_to_kernel(uservaddr, addrlen, &address);
|
||||||
if (!ret)
|
if (ret)
|
||||||
ret = __sys_connect_file(fd_file(f), &address, addrlen, 0);
|
return ret;
|
||||||
fdput(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return __sys_connect_file(fd_file(f), &address, addrlen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
|
SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
|
||||||
@ -2108,26 +2088,25 @@ int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
|
|||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
struct sockaddr_storage address;
|
struct sockaddr_storage address;
|
||||||
int err, fput_needed;
|
CLASS(fd, f)(fd);
|
||||||
|
int err;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (!sock)
|
return -EBADF;
|
||||||
goto out;
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
err = security_socket_getsockname(sock);
|
err = security_socket_getsockname(sock);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put;
|
return err;
|
||||||
|
|
||||||
err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
|
err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_put;
|
return err;
|
||||||
/* "err" is actually length in this case */
|
|
||||||
err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
|
|
||||||
|
|
||||||
out_put:
|
/* "err" is actually length in this case */
|
||||||
fput_light(sock->file, fput_needed);
|
return move_addr_to_user(&address, err, usockaddr, usockaddr_len);
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
|
SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
|
||||||
@ -2146,26 +2125,25 @@ int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
|
|||||||
{
|
{
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
struct sockaddr_storage address;
|
struct sockaddr_storage address;
|
||||||
int err, fput_needed;
|
CLASS(fd, f)(fd);
|
||||||
|
int err;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (sock != NULL) {
|
return -EBADF;
|
||||||
const struct proto_ops *ops = READ_ONCE(sock->ops);
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
err = security_socket_getpeername(sock);
|
err = security_socket_getpeername(sock);
|
||||||
if (err) {
|
if (err)
|
||||||
fput_light(sock->file, fput_needed);
|
return err;
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ops->getname(sock, (struct sockaddr *)&address, 1);
|
err = READ_ONCE(sock->ops)->getname(sock, (struct sockaddr *)&address, 1);
|
||||||
if (err >= 0)
|
if (err < 0)
|
||||||
/* "err" is actually length in this case */
|
return err;
|
||||||
err = move_addr_to_user(&address, err, usockaddr,
|
|
||||||
usockaddr_len);
|
/* "err" is actually length in this case */
|
||||||
fput_light(sock->file, fput_needed);
|
return move_addr_to_user(&address, err, usockaddr, usockaddr_len);
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
|
SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
|
||||||
@ -2186,14 +2164,17 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
|
|||||||
struct sockaddr_storage address;
|
struct sockaddr_storage address;
|
||||||
int err;
|
int err;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
int fput_needed;
|
|
||||||
|
|
||||||
err = import_ubuf(ITER_SOURCE, buff, len, &msg.msg_iter);
|
err = import_ubuf(ITER_SOURCE, buff, len, &msg.msg_iter);
|
||||||
if (unlikely(err))
|
if (unlikely(err))
|
||||||
return err;
|
return err;
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
|
||||||
if (!sock)
|
CLASS(fd, f)(fd);
|
||||||
goto out;
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
msg.msg_name = NULL;
|
msg.msg_name = NULL;
|
||||||
msg.msg_control = NULL;
|
msg.msg_control = NULL;
|
||||||
@ -2203,7 +2184,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
|
|||||||
if (addr) {
|
if (addr) {
|
||||||
err = move_addr_to_kernel(addr, addr_len, &address);
|
err = move_addr_to_kernel(addr, addr_len, &address);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_put;
|
return err;
|
||||||
msg.msg_name = (struct sockaddr *)&address;
|
msg.msg_name = (struct sockaddr *)&address;
|
||||||
msg.msg_namelen = addr_len;
|
msg.msg_namelen = addr_len;
|
||||||
}
|
}
|
||||||
@ -2211,12 +2192,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags,
|
|||||||
if (sock->file->f_flags & O_NONBLOCK)
|
if (sock->file->f_flags & O_NONBLOCK)
|
||||||
flags |= MSG_DONTWAIT;
|
flags |= MSG_DONTWAIT;
|
||||||
msg.msg_flags = flags;
|
msg.msg_flags = flags;
|
||||||
err = __sock_sendmsg(sock, &msg);
|
return __sock_sendmsg(sock, &msg);
|
||||||
|
|
||||||
out_put:
|
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
|
SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
|
||||||
@ -2251,14 +2227,18 @@ int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
|
|||||||
};
|
};
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
int err, err2;
|
int err, err2;
|
||||||
int fput_needed;
|
|
||||||
|
|
||||||
err = import_ubuf(ITER_DEST, ubuf, size, &msg.msg_iter);
|
err = import_ubuf(ITER_DEST, ubuf, size, &msg.msg_iter);
|
||||||
if (unlikely(err))
|
if (unlikely(err))
|
||||||
return err;
|
return err;
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
|
||||||
if (!sock)
|
CLASS(fd, f)(fd);
|
||||||
goto out;
|
|
||||||
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
if (sock->file->f_flags & O_NONBLOCK)
|
if (sock->file->f_flags & O_NONBLOCK)
|
||||||
flags |= MSG_DONTWAIT;
|
flags |= MSG_DONTWAIT;
|
||||||
@ -2270,9 +2250,6 @@ int __sys_recvfrom(int fd, void __user *ubuf, size_t size, unsigned int flags,
|
|||||||
if (err2 < 0)
|
if (err2 < 0)
|
||||||
err = err2;
|
err = err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
out:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2347,17 +2324,16 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
|
|||||||
{
|
{
|
||||||
sockptr_t optval = USER_SOCKPTR(user_optval);
|
sockptr_t optval = USER_SOCKPTR(user_optval);
|
||||||
bool compat = in_compat_syscall();
|
bool compat = in_compat_syscall();
|
||||||
int err, fput_needed;
|
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
|
CLASS(fd, f)(fd);
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (!sock)
|
return -EBADF;
|
||||||
return err;
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
err = do_sock_setsockopt(sock, compat, level, optname, optval, optlen);
|
return do_sock_setsockopt(sock, compat, level, optname, optval, optlen);
|
||||||
|
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
|
SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
|
||||||
@ -2413,20 +2389,17 @@ EXPORT_SYMBOL(do_sock_getsockopt);
|
|||||||
int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
|
int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
|
||||||
int __user *optlen)
|
int __user *optlen)
|
||||||
{
|
{
|
||||||
int err, fput_needed;
|
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
bool compat;
|
CLASS(fd, f)(fd);
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (!sock)
|
return -EBADF;
|
||||||
return err;
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
compat = in_compat_syscall();
|
return do_sock_getsockopt(sock, in_compat_syscall(), level, optname,
|
||||||
err = do_sock_getsockopt(sock, compat, level, optname,
|
|
||||||
USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
|
USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
|
||||||
|
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
|
SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
|
||||||
@ -2452,15 +2425,16 @@ int __sys_shutdown_sock(struct socket *sock, int how)
|
|||||||
|
|
||||||
int __sys_shutdown(int fd, int how)
|
int __sys_shutdown(int fd, int how)
|
||||||
{
|
{
|
||||||
int err, fput_needed;
|
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
|
CLASS(fd, f)(fd);
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
if (fd_empty(f))
|
||||||
if (sock != NULL) {
|
return -EBADF;
|
||||||
err = __sys_shutdown_sock(sock, how);
|
sock = sock_from_file(fd_file(f));
|
||||||
fput_light(sock->file, fput_needed);
|
if (unlikely(!sock))
|
||||||
}
|
return -ENOTSOCK;
|
||||||
return err;
|
|
||||||
|
return __sys_shutdown_sock(sock, how);
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE2(shutdown, int, fd, int, how)
|
SYSCALL_DEFINE2(shutdown, int, fd, int, how)
|
||||||
@ -2676,22 +2650,21 @@ long __sys_sendmsg_sock(struct socket *sock, struct msghdr *msg,
|
|||||||
long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
|
long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
|
||||||
bool forbid_cmsg_compat)
|
bool forbid_cmsg_compat)
|
||||||
{
|
{
|
||||||
int fput_needed, err;
|
|
||||||
struct msghdr msg_sys;
|
struct msghdr msg_sys;
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
|
|
||||||
if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
|
if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
CLASS(fd, f)(fd);
|
||||||
if (!sock)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
fput_light(sock->file, fput_needed);
|
return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
|
SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
|
||||||
@ -2706,7 +2679,7 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int
|
|||||||
int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
||||||
unsigned int flags, bool forbid_cmsg_compat)
|
unsigned int flags, bool forbid_cmsg_compat)
|
||||||
{
|
{
|
||||||
int fput_needed, err, datagrams;
|
int err, datagrams;
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
struct mmsghdr __user *entry;
|
struct mmsghdr __user *entry;
|
||||||
struct compat_mmsghdr __user *compat_entry;
|
struct compat_mmsghdr __user *compat_entry;
|
||||||
@ -2722,9 +2695,13 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
|||||||
|
|
||||||
datagrams = 0;
|
datagrams = 0;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
CLASS(fd, f)(fd);
|
||||||
if (!sock)
|
|
||||||
return err;
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
used_address.name_len = UINT_MAX;
|
used_address.name_len = UINT_MAX;
|
||||||
entry = mmsg;
|
entry = mmsg;
|
||||||
@ -2761,8 +2738,6 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
|||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
|
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
|
|
||||||
/* We only return an error if no datagrams were able to be sent */
|
/* We only return an error if no datagrams were able to be sent */
|
||||||
if (datagrams != 0)
|
if (datagrams != 0)
|
||||||
return datagrams;
|
return datagrams;
|
||||||
@ -2884,22 +2859,21 @@ long __sys_recvmsg_sock(struct socket *sock, struct msghdr *msg,
|
|||||||
long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
|
long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
|
||||||
bool forbid_cmsg_compat)
|
bool forbid_cmsg_compat)
|
||||||
{
|
{
|
||||||
int fput_needed, err;
|
|
||||||
struct msghdr msg_sys;
|
struct msghdr msg_sys;
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
|
|
||||||
if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
|
if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
CLASS(fd, f)(fd);
|
||||||
if (!sock)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
fput_light(sock->file, fput_needed);
|
return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
|
||||||
out:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
|
SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
|
||||||
@ -2916,7 +2890,7 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
|
|||||||
unsigned int vlen, unsigned int flags,
|
unsigned int vlen, unsigned int flags,
|
||||||
struct timespec64 *timeout)
|
struct timespec64 *timeout)
|
||||||
{
|
{
|
||||||
int fput_needed, err, datagrams;
|
int err = 0, datagrams;
|
||||||
struct socket *sock;
|
struct socket *sock;
|
||||||
struct mmsghdr __user *entry;
|
struct mmsghdr __user *entry;
|
||||||
struct compat_mmsghdr __user *compat_entry;
|
struct compat_mmsghdr __user *compat_entry;
|
||||||
@ -2931,16 +2905,18 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
|
|||||||
|
|
||||||
datagrams = 0;
|
datagrams = 0;
|
||||||
|
|
||||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
CLASS(fd, f)(fd);
|
||||||
if (!sock)
|
|
||||||
return err;
|
if (fd_empty(f))
|
||||||
|
return -EBADF;
|
||||||
|
sock = sock_from_file(fd_file(f));
|
||||||
|
if (unlikely(!sock))
|
||||||
|
return -ENOTSOCK;
|
||||||
|
|
||||||
if (likely(!(flags & MSG_ERRQUEUE))) {
|
if (likely(!(flags & MSG_ERRQUEUE))) {
|
||||||
err = sock_error(sock->sk);
|
err = sock_error(sock->sk);
|
||||||
if (err) {
|
if (err)
|
||||||
datagrams = err;
|
return err;
|
||||||
goto out_put;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = mmsg;
|
entry = mmsg;
|
||||||
@ -2997,12 +2973,10 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
goto out_put;
|
return datagrams;
|
||||||
|
|
||||||
if (datagrams == 0) {
|
if (datagrams == 0)
|
||||||
datagrams = err;
|
return err;
|
||||||
goto out_put;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may return less entries than requested (vlen) if the
|
* We may return less entries than requested (vlen) if the
|
||||||
@ -3017,9 +2991,6 @@ static int do_recvmmsg(int fd, struct mmsghdr __user *mmsg,
|
|||||||
*/
|
*/
|
||||||
WRITE_ONCE(sock->sk->sk_err, -err);
|
WRITE_ONCE(sock->sk->sk_err, -err);
|
||||||
}
|
}
|
||||||
out_put:
|
|
||||||
fput_light(sock->file, fput_needed);
|
|
||||||
|
|
||||||
return datagrams;
|
return datagrams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,19 +1062,16 @@ out:
|
|||||||
*/
|
*/
|
||||||
void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
|
void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
|
|
||||||
if (!buf || !size)
|
if (!buf || !size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
f = fdget(kernel_fd);
|
CLASS(fd, f)(kernel_fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
process_buffer_measurement(file_mnt_idmap(fd_file(f)), file_inode(fd_file(f)),
|
process_buffer_measurement(file_mnt_idmap(fd_file(f)), file_inode(fd_file(f)),
|
||||||
buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
|
buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
|
||||||
NULL, false, NULL, 0);
|
NULL, false, NULL, 0);
|
||||||
fdput(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,31 +241,21 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
|
|||||||
static struct landlock_ruleset *get_ruleset_from_fd(const int fd,
|
static struct landlock_ruleset *get_ruleset_from_fd(const int fd,
|
||||||
const fmode_t mode)
|
const fmode_t mode)
|
||||||
{
|
{
|
||||||
struct fd ruleset_f;
|
CLASS(fd, ruleset_f)(fd);
|
||||||
struct landlock_ruleset *ruleset;
|
struct landlock_ruleset *ruleset;
|
||||||
|
|
||||||
ruleset_f = fdget(fd);
|
if (fd_empty(ruleset_f))
|
||||||
if (!fd_file(ruleset_f))
|
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
/* Checks FD type and access right. */
|
/* Checks FD type and access right. */
|
||||||
if (fd_file(ruleset_f)->f_op != &ruleset_fops) {
|
if (fd_file(ruleset_f)->f_op != &ruleset_fops)
|
||||||
ruleset = ERR_PTR(-EBADFD);
|
return ERR_PTR(-EBADFD);
|
||||||
goto out_fdput;
|
if (!(fd_file(ruleset_f)->f_mode & mode))
|
||||||
}
|
return ERR_PTR(-EPERM);
|
||||||
if (!(fd_file(ruleset_f)->f_mode & mode)) {
|
|
||||||
ruleset = ERR_PTR(-EPERM);
|
|
||||||
goto out_fdput;
|
|
||||||
}
|
|
||||||
ruleset = fd_file(ruleset_f)->private_data;
|
ruleset = fd_file(ruleset_f)->private_data;
|
||||||
if (WARN_ON_ONCE(ruleset->num_layers != 1)) {
|
if (WARN_ON_ONCE(ruleset->num_layers != 1))
|
||||||
ruleset = ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
goto out_fdput;
|
|
||||||
}
|
|
||||||
landlock_get_ruleset(ruleset);
|
landlock_get_ruleset(ruleset);
|
||||||
|
|
||||||
out_fdput:
|
|
||||||
fdput(ruleset_f);
|
|
||||||
return ruleset;
|
return ruleset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,15 +266,12 @@ out_fdput:
|
|||||||
*/
|
*/
|
||||||
static int get_path_from_fd(const s32 fd, struct path *const path)
|
static int get_path_from_fd(const s32 fd, struct path *const path)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd_raw, f)(fd);
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
BUILD_BUG_ON(!__same_type(
|
BUILD_BUG_ON(!__same_type(
|
||||||
fd, ((struct landlock_path_beneath_attr *)NULL)->parent_fd));
|
fd, ((struct landlock_path_beneath_attr *)NULL)->parent_fd));
|
||||||
|
|
||||||
/* Handles O_PATH. */
|
if (fd_empty(f))
|
||||||
f = fdget_raw(fd);
|
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
/*
|
/*
|
||||||
* Forbids ruleset FDs, internal filesystems (e.g. nsfs), including
|
* Forbids ruleset FDs, internal filesystems (e.g. nsfs), including
|
||||||
@ -295,16 +282,12 @@ static int get_path_from_fd(const s32 fd, struct path *const path)
|
|||||||
(fd_file(f)->f_path.mnt->mnt_flags & MNT_INTERNAL) ||
|
(fd_file(f)->f_path.mnt->mnt_flags & MNT_INTERNAL) ||
|
||||||
(fd_file(f)->f_path.dentry->d_sb->s_flags & SB_NOUSER) ||
|
(fd_file(f)->f_path.dentry->d_sb->s_flags & SB_NOUSER) ||
|
||||||
d_is_negative(fd_file(f)->f_path.dentry) ||
|
d_is_negative(fd_file(f)->f_path.dentry) ||
|
||||||
IS_PRIVATE(d_backing_inode(fd_file(f)->f_path.dentry))) {
|
IS_PRIVATE(d_backing_inode(fd_file(f)->f_path.dentry)))
|
||||||
err = -EBADFD;
|
return -EBADFD;
|
||||||
goto out_fdput;
|
|
||||||
}
|
|
||||||
*path = fd_file(f)->f_path;
|
*path = fd_file(f)->f_path;
|
||||||
path_get(path);
|
path_get(path);
|
||||||
|
return 0;
|
||||||
out_fdput:
|
|
||||||
fdput(f);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_rule_path_beneath(struct landlock_ruleset *const ruleset,
|
static int add_rule_path_beneath(struct landlock_ruleset *const ruleset,
|
||||||
|
@ -283,7 +283,6 @@ enum loadpin_securityfs_interface_index {
|
|||||||
|
|
||||||
static int read_trusted_verity_root_digests(unsigned int fd)
|
static int read_trusted_verity_root_digests(unsigned int fd)
|
||||||
{
|
{
|
||||||
struct fd f;
|
|
||||||
void *data;
|
void *data;
|
||||||
int rc;
|
int rc;
|
||||||
char *p, *d;
|
char *p, *d;
|
||||||
@ -295,8 +294,8 @@ static int read_trusted_verity_root_digests(unsigned int fd)
|
|||||||
if (!list_empty(&dm_verity_loadpin_trusted_root_digests))
|
if (!list_empty(&dm_verity_loadpin_trusted_root_digests))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
f = fdget(fd);
|
CLASS(fd, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
data = kzalloc(SZ_4K, GFP_KERNEL);
|
data = kzalloc(SZ_4K, GFP_KERNEL);
|
||||||
@ -359,7 +358,6 @@ static int read_trusted_verity_root_digests(unsigned int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
kfree(data);
|
kfree(data);
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -379,8 +377,6 @@ err:
|
|||||||
/* disallow further attempts after reading a corrupt/invalid file */
|
/* disallow further attempts after reading a corrupt/invalid file */
|
||||||
deny_reading_verity_digests = true;
|
deny_reading_verity_digests = true;
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2250,7 +2250,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
|||||||
bool nonatomic = substream->pcm->nonatomic;
|
bool nonatomic = substream->pcm->nonatomic;
|
||||||
CLASS(fd, f)(fd);
|
CLASS(fd, f)(fd);
|
||||||
|
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
if (!is_pcm_file(fd_file(f)))
|
if (!is_pcm_file(fd_file(f)))
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
@ -304,7 +304,6 @@ static int
|
|||||||
kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||||
{
|
{
|
||||||
struct kvm_kernel_irqfd *irqfd, *tmp;
|
struct kvm_kernel_irqfd *irqfd, *tmp;
|
||||||
struct fd f;
|
|
||||||
struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
|
struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
@ -327,8 +326,8 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
|
INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
|
||||||
seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock);
|
seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock);
|
||||||
|
|
||||||
f = fdget(args->fd);
|
CLASS(fd, f)(args->fd);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -336,7 +335,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
eventfd = eventfd_ctx_fileget(fd_file(f));
|
eventfd = eventfd_ctx_fileget(fd_file(f));
|
||||||
if (IS_ERR(eventfd)) {
|
if (IS_ERR(eventfd)) {
|
||||||
ret = PTR_ERR(eventfd);
|
ret = PTR_ERR(eventfd);
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
irqfd->eventfd = eventfd;
|
irqfd->eventfd = eventfd;
|
||||||
@ -440,12 +439,6 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
srcu_read_unlock(&kvm->irq_srcu, idx);
|
||||||
|
|
||||||
/*
|
|
||||||
* do not drop the file until the irqfd is fully initialized, otherwise
|
|
||||||
* we might race against the EPOLLHUP
|
|
||||||
*/
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -458,8 +451,6 @@ fail:
|
|||||||
if (eventfd && !IS_ERR(eventfd))
|
if (eventfd && !IS_ERR(eventfd))
|
||||||
eventfd_ctx_put(eventfd);
|
eventfd_ctx_put(eventfd);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(irqfd);
|
kfree(irqfd);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -190,11 +190,10 @@ static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd)
|
|||||||
{
|
{
|
||||||
struct kvm_vfio *kv = dev->private;
|
struct kvm_vfio *kv = dev->private;
|
||||||
struct kvm_vfio_file *kvf;
|
struct kvm_vfio_file *kvf;
|
||||||
struct fd f;
|
CLASS(fd, f)(fd);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
f = fdget(fd);
|
if (fd_empty(f))
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
@ -220,9 +219,6 @@ static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd)
|
|||||||
kvm_vfio_update_coherency(dev);
|
kvm_vfio_update_coherency(dev);
|
||||||
|
|
||||||
mutex_unlock(&kv->lock);
|
mutex_unlock(&kv->lock);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,14 +229,13 @@ static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev,
|
|||||||
struct kvm_vfio_spapr_tce param;
|
struct kvm_vfio_spapr_tce param;
|
||||||
struct kvm_vfio *kv = dev->private;
|
struct kvm_vfio *kv = dev->private;
|
||||||
struct kvm_vfio_file *kvf;
|
struct kvm_vfio_file *kvf;
|
||||||
struct fd f;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (copy_from_user(¶m, arg, sizeof(struct kvm_vfio_spapr_tce)))
|
if (copy_from_user(¶m, arg, sizeof(struct kvm_vfio_spapr_tce)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
f = fdget(param.groupfd);
|
CLASS(fd, f)(param.groupfd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
@ -266,7 +261,6 @@ static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev,
|
|||||||
|
|
||||||
err_fdput:
|
err_fdput:
|
||||||
mutex_unlock(&kv->lock);
|
mutex_unlock(&kv->lock);
|
||||||
fdput(f);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user