/** * bus1_import_fd() - import file descriptor from user * @user_fd: pointer to user-supplied file descriptor * * This imports a file-descriptor from the current user-context. The FD number * is copied into kernel-space, then resolved to a file and returned to the * caller. If something goes wrong, an error is returned. * * Neither bus1, nor UDS files are allowed. If those are supplied, EOPNOTSUPP * is returned. Those would require expensive garbage-collection if they're * sent recursively by user-space. * * Return: Pointer to pinned file, ERR_PTR on failure. */ struct file *bus1_import_fd(const u32 __user *user_fd) { struct file *f, *ret; struct socket *sock; struct inode *inode; int fd; if (unlikely(get_user(fd, user_fd))) return ERR_PTR(-EFAULT); if (unlikely(fd < 0)) return ERR_PTR(-EBADF); f = fget_raw(fd); if (unlikely(!f)) return ERR_PTR(-EBADF); inode = file_inode(f); sock = S_ISSOCK(inode->i_mode) ? SOCKET_I(inode) : NULL; if (f->f_mode & FMODE_PATH) ret = f; /* O_PATH is always allowed */ else if (f->f_op == &bus1_fs_bus_fops) ret = ERR_PTR(-EOPNOTSUPP); /* disallow bus1 recursion */ else if (sock && sock->sk && sock->ops && sock->ops->family == PF_UNIX) ret = ERR_PTR(-EOPNOTSUPP); /* disallow UDS recursion */ else ret = f; /* all others are allowed */ if (f != ret) fput(f); return ret; }
void fuse_setup_shortcircuit(struct fuse_conn *fc, struct fuse_req *req) { int daemon_fd; struct file *rw_lower_file = NULL; struct fuse_open_out *open_out; int open_out_index; req->private_lower_rw_file = NULL; if (!(fc->shortcircuit_io)) return; if ((req->in.h.opcode != FUSE_OPEN) && (req->in.h.opcode != FUSE_CREATE)) return; open_out_index = req->in.numargs - 1; BUG_ON(open_out_index != 0 && open_out_index != 1); BUG_ON(req->out.args[open_out_index].size != sizeof(*open_out)); open_out = req->out.args[open_out_index].value; daemon_fd = (int)open_out->lower_fd; if (daemon_fd < 0) return; rw_lower_file = fget_raw(daemon_fd); if (!rw_lower_file) return; req->private_lower_rw_file = rw_lower_file; }
int fd_statfs(int fd, struct kstatfs *st) { struct file *file = fget_raw(fd); int error = -EBADF; if (file) { error = vfs_statfs(&file->f_path, st); fput(file); } return error; }
int vfs_fstat(unsigned int fd, struct kstat *stat) { struct file *f = fget_raw(fd); int error = -EBADF; if (f) { error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); fput(f); } return error; }
static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) { int *fdp = (int*)CMSG_DATA(cmsg); struct scm_fp_list *fpl = *fplp; struct file **fpp; int i, num; num = (cmsg->cmsg_len - sizeof(struct cmsghdr))/sizeof(int); if (num <= 0) return 0; if (num > SCM_MAX_FD) return -EINVAL; if (!fpl) { fpl = kmalloc(sizeof(struct scm_fp_list), GFP_KERNEL); if (!fpl) return -ENOMEM; *fplp = fpl; fpl->count = 0; fpl->max = SCM_MAX_FD; fpl->user = NULL; } fpp = &fpl->fp[fpl->count]; if (fpl->count + num > fpl->max) return -EINVAL; /* * Verify the descriptors and increment the usage count. */ for (i=0; i< num; i++) { int fd = fdp[i]; struct file *file; if (fd < 0 || !(file = fget_raw(fd))) return -EBADF; *fpp++ = file; fpl->count++; } if (!fpl->user) fpl->user = get_uid(current_user()); return num; }
if (retval) return retval; if (inode->i_op->getattr) return inode->i_op->getattr(mnt, dentry, stat); generic_fillattr(inode, stat); return 0; } EXPORT_SYMBOL(vfs_getattr); int vfs_fstat(unsigned int fd, struct kstat *stat) { <<<<<<< HEAD struct file *f = fget_raw(fd); ======= struct file *f = fget(fd); >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a int error = -EBADF; if (f) { error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); fput(f); } return error; } EXPORT_SYMBOL(vfs_fstat); <<<<<<< HEAD int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,