struct file * afs_linux_raw_open(afs_dcache_id_t *ainode) { struct inode *tip = NULL; struct dentry *dp = NULL; struct file* filp; dp = afs_get_dentry_from_fh(afs_cacheSBp, ainode, cache_fh_len, cache_fh_type, afs_fh_acceptable); if ((!dp) || IS_ERR(dp)) osi_Panic("Can't get dentry\n"); tip = dp->d_inode; tip->i_flags |= S_NOATIME; /* Disable updating access times. */ #if defined(STRUCT_TASK_STRUCT_HAS_CRED) /* Use stashed credentials - prevent selinux/apparmor problems */ filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR, cache_creds); if (IS_ERR(filp)) filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR, current_cred()); #else filp = dentry_open(dp, mntget(afs_cacheMnt), O_RDWR); #endif if (IS_ERR(filp)) osi_Panic("Can't open file: %d\n", (int) PTR_ERR(filp)); return filp; }
static struct file *do_open(char *name, int flags) { struct nameidata nd; int error; nd.mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); if (IS_ERR(nd.mnt)) return (struct file *)nd.mnt; nd.dentry = dget(nd.mnt->mnt_root); nd.last_type = LAST_ROOT; nd.flags = 0; nd.depth = 0; error = path_walk(name, &nd); if (error) return ERR_PTR(error); if (flags == O_RDWR) error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE); else error = may_open(&nd, MAY_WRITE, FMODE_WRITE); if (!error) return dentry_open(nd.dentry, nd.mnt, flags); path_release(&nd); return ERR_PTR(error); }
static int __open_dir(struct inode *inode, struct file *file, struct dentry *parent) { struct dentry *lower_dentry; struct file *lower_file; struct vfsmount *lower_mnt; struct dentry *dentry = file->f_path.dentry; int i = 0, idx = 0; for (i = 0; i <= 1; i++) { lower_dentry = wrapfs_lower_dentry_idx(dentry, i); if (!lower_dentry || !lower_dentry->d_inode) continue; dget(lower_dentry); lower_mnt = mntget(wrapfs_lower_mnt_idx(dentry, i)); if (!lower_mnt) lower_mnt = mntget(wrapfs_lower_mnt_idx(parent, i)); lower_file = dentry_open(lower_dentry, lower_mnt, file->f_flags, current_cred()); if (IS_ERR(lower_file)) return PTR_ERR(lower_file); wrapfs_set_lower_file_idx(file, i, lower_file); if (!wrapfs_lower_mnt_idx(dentry, i)) wrapfs_set_lower_mnt_idx(dentry, i, lower_mnt); branchget(inode->i_sb, i); idx = i; } fsstack_copy_attr_all(inode, wrapfs_lower_inode_idx(inode, idx)); return 0; }
/* * Open a file descriptor on the autofs mount point corresponding * to the given path and device number (aka. new_encode_dev(sb->s_dev)). */ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid) { int err, fd; fd = get_unused_fd_flags(O_CLOEXEC); if (likely(fd >= 0)) { struct file *filp; struct path path; err = find_autofs_mount(name, &path, test_by_dev, &devid); if (err) goto out; filp = dentry_open(&path, O_RDONLY, current_cred()); path_put(&path); if (IS_ERR(filp)) { err = PTR_ERR(filp); goto out; } fd_install(fd, filp); } return fd; out: put_unused_fd(fd); return err; }
/* open all lower files for a given file */ static int open_all_files(struct file *file) { int bindex, bstart, bend, err = 0; struct file *lower_file; struct dentry *lower_dentry; struct dentry *dentry = file->f_path.dentry; struct super_block *sb = dentry->d_sb; bstart = dbstart(dentry); bend = dbend(dentry); for (bindex = bstart; bindex <= bend; bindex++) { lower_dentry = unionfs_lower_dentry_idx(dentry, bindex); if (!lower_dentry) continue; dget(lower_dentry); unionfs_mntget(dentry, bindex); branchget(sb, bindex); lower_file = dentry_open(lower_dentry, unionfs_lower_mnt_idx(dentry, bindex), file->f_flags, current_cred()); if (IS_ERR(lower_file)) { branchput(sb, bindex); err = PTR_ERR(lower_file); goto out; } else { unionfs_set_lower_file_idx(file, bindex, lower_file); } } out: return err; }
struct file * afs_linux_raw_open(afs_dcache_id_t *ainode) { struct inode *tip = NULL; struct dentry *dp = NULL; struct file* filp; dp = afs_get_dentry_from_fh(afs_cacheSBp, ainode, cache_fh_len, cache_fh_type, afs_fh_acceptable); if ((!dp) || IS_ERR(dp)) osi_Panic("Can't get dentry\n"); tip = dp->d_inode; tip->i_flags |= S_NOATIME; /* Disable updating access times. */ #if defined(STRUCT_TASK_STRUCT_HAS_CRED) /* Use stashed credentials - prevent selinux/apparmor problems */ filp = afs_dentry_open(dp, afs_cacheMnt, O_RDWR, cache_creds); if (IS_ERR(filp)) filp = afs_dentry_open(dp, afs_cacheMnt, O_RDWR, current_cred()); #else filp = dentry_open(dget(dp), mntget(afs_cacheMnt), O_RDWR); #endif if (IS_ERR(filp)) { afs_warn("afs: Cannot open cache file (code %d). Trying to continue, " "but AFS accesses may return errors or panic the system\n", (int) PTR_ERR(filp)); filp = NULL; } dput(dp); return filp; }
static struct file *do_open(char *name, int flags) { struct nameidata nd; struct vfsmount *mnt; int error; mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); if (IS_ERR(mnt)) return (struct file *)mnt; error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd); mntput(mnt); /* drop do_kern_mount reference */ if (error) return ERR_PTR(error); if (flags == O_RDWR) error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE); else error = may_open(&nd, MAY_WRITE, FMODE_WRITE); if (!error) return dentry_open(nd.path.dentry, nd.path.mnt, flags); path_put(&nd.path); return ERR_PTR(error); }
/* unionfs_open helper function: open a directory */ static int __open_dir(struct inode *inode, struct file *file) { struct dentry *lower_dentry; struct file *lower_file; int bindex, bstart, bend; struct vfsmount *mnt; bstart = fbstart(file) = dbstart(file->f_path.dentry); bend = fbend(file) = dbend(file->f_path.dentry); for (bindex = bstart; bindex <= bend; bindex++) { lower_dentry = unionfs_lower_dentry_idx(file->f_path.dentry, bindex); if (!lower_dentry) continue; dget(lower_dentry); unionfs_mntget(file->f_path.dentry, bindex); mnt = unionfs_lower_mnt_idx(file->f_path.dentry, bindex); lower_file = dentry_open(lower_dentry, mnt, file->f_flags, current_cred()); if (IS_ERR(lower_file)) return PTR_ERR(lower_file); unionfs_set_lower_file_idx(file, bindex, lower_file); /* * The branchget goes after the open, because otherwise * we would miss the reference on release. */ branchget(inode->i_sb, bindex); } return 0; }
static int nfsio_prepare_snapshot(struct ploop_io * io, struct ploop_snapdata *sd) { int err; struct file * file = io->files.file; file = dentry_open(dget(F_DENTRY(file)), mntget(F_MNT(file)), O_RDONLY|O_LARGEFILE, current_cred()); if (IS_ERR(file)) return PTR_ERR(file); /* Sanity checks */ if (io->files.mapping != file->f_mapping || io->files.inode != file->f_mapping->host) { fput(file); return -EINVAL; } err = invalidate_inode_pages2(file->f_mapping); if (err) { fput(file); return err; } sd->file = file; return 0; }
/* * Open a file descriptor on the autofs mount point corresponding * to the given path and device number (aka. new_encode_dev(sb->s_dev)). */ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid) { int err, fd; fd = get_unused_fd(); if (likely(fd >= 0)) { struct file *filp; struct path path; err = find_autofs_mount(name, &path, test_by_dev, &devid); if (err) goto out; /* * Find autofs super block that has the device number * corresponding to the autofs fs we want to open. */ filp = dentry_open(path.dentry, path.mnt, O_RDONLY, current_cred()); if (IS_ERR(filp)) { err = PTR_ERR(filp); goto out; } autofs_dev_ioctl_fd_install(fd, filp); } return fd; out: put_unused_fd(fd); return err; }
/* * read the key data * - the key's semaphore is read-locked */ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) { size_t datalen = (size_t)key->payload.data[big_key_len]; long ret; if (!buffer || buflen < datalen) return datalen; if (datalen > BIG_KEY_FILE_THRESHOLD) { struct path *path = (struct path *)&key->payload.data[big_key_path]; struct file *file; loff_t pos; file = dentry_open(path, O_RDONLY, current_cred()); if (IS_ERR(file)) return PTR_ERR(file); pos = 0; ret = vfs_read(file, buffer, datalen, &pos); fput(file); if (ret >= 0 && ret != datalen) ret = -EIO; } else { ret = datalen; if (copy_to_user(buffer, key->payload.data[big_key_data], datalen) != 0) ret = -EFAULT; } return ret; }
/* Call dentry_open(). * Caller should path_get() (or dget() and mntget()) just as they would for dentry_open(). */ struct file * cr_dentry_open(struct path *path, int flags) { struct file *filp; #if !HAVE_TASK_CRED filp = dentry_open(path->dentry, path->mnt, flags); #elif HAVE_4_ARG_DENTRY_OPEN filp = dentry_open(path->dentry, path->mnt, flags, cr_current_cred()); #elif HAVE_3_ARG_DENTRY_OPEN filp = dentry_open(path, flags, cr_current_cred()); path_put(path); // dentry_open takes the ref count now #endif return filp; }
/* Call permision() and dentry_open(). * Caller should dget() and mntget() just as they would for dentry_open(). */ struct file * cr_dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) { struct file *filp; int acc_mask = ("\000\004\002\006"[(flags)&O_ACCMODE]); /* ICK (from linux/fs/namei.c) */ int err; err = cr_permission(dentry->d_inode, acc_mask, NULL); filp = ERR_PTR(err); #if HAVE_TASK_CRED if (!IS_ERR(filp)) filp = dentry_open(dentry, mnt, flags, cr_current_cred()); #else if (!IS_ERR(filp)) filp = dentry_open(dentry, mnt, flags); #endif return filp; }
/** * ima_path_check - based on policy, collect/store measurement. * @path: contains a pointer to the path to be measured * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE * * Measure the file being open for readonly, based on the * ima_must_measure() policy decision. * * Keep read/write counters for all files, but only * invalidate the PCR for measured files: * - Opening a file for write when already open for read, * results in a time of measure, time of use (ToMToU) error. * - Opening a file for read when already open for write, * could result in a file measurement error. * * Always return 0 and audit dentry_open failures. * (Return code will be based upon measurement appraisal.) */ int ima_path_check(struct path *path, int mask, int update_counts) { struct inode *inode = path->dentry->d_inode; struct ima_iint_cache *iint; struct file *file = NULL; int rc; if (!ima_initialized || !S_ISREG(inode->i_mode)) return 0; iint = ima_iint_find_insert_get(inode); if (!iint) return 0; mutex_lock(&iint->mutex); if (update_counts) ima_update_counts(iint, mask); rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); if (rc < 0) goto out; if ((mask & MAY_WRITE) || (mask == 0)) ima_read_write_check(TOMTOU, iint, inode, path->dentry->d_name.name); if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ) goto out; ima_read_write_check(OPEN_WRITERS, iint, inode, path->dentry->d_name.name); if (!(iint->flags & IMA_MEASURED)) { struct dentry *dentry = dget(path->dentry); struct vfsmount *mnt = mntget(path->mnt); file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, current_cred()); if (IS_ERR(file)) { int audit_info = 0; integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, dentry->d_name.name, "add_measurement", "dentry_open failed", 1, audit_info); file = NULL; goto out; } rc = get_path_measurement(iint, file, dentry->d_name.name); } out: mutex_unlock(&iint->mutex); if (file) fput(file); kref_put(&iint->refcount, iint_free); return 0; }
/* * read the key data * - the key's semaphore is read-locked */ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) { size_t datalen = (size_t)key->payload.data[big_key_len]; long ret; if (!buffer || buflen < datalen) return datalen; if (datalen > BIG_KEY_FILE_THRESHOLD) { struct path *path = (struct path *)&key->payload.data[big_key_path]; struct file *file; u8 *data; u8 *enckey = (u8 *)key->payload.data[big_key_data]; size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher)); loff_t pos = 0; data = kmalloc(enclen, GFP_KERNEL); if (!data) return -ENOMEM; file = dentry_open(path, O_RDONLY, current_cred()); if (IS_ERR(file)) { ret = PTR_ERR(file); goto error; } /* read file to kernel and decrypt */ ret = kernel_read(file, data, enclen, &pos); if (ret >= 0 && ret != enclen) { ret = -EIO; goto err_fput; } ret = big_key_crypt(BIG_KEY_DEC, data, enclen, enckey); if (ret) goto err_fput; ret = datalen; /* copy decrypted data to user */ if (copy_to_user(buffer, data, datalen) != 0) ret = -EFAULT; err_fput: fput(file); error: kfree(data); } else { ret = datalen; if (copy_to_user(buffer, key->payload.data[big_key_data], datalen) != 0) ret = -EFAULT; } return ret; }
/* common functions to regular file and dir */ struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags) { struct dentry *hidden_dentry; struct inode *hidden_inode; struct super_block *sb; struct vfsmount *hidden_mnt; struct file *hidden_file; struct aufs_branch *br; loff_t old_size; int udba; LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags); DEBUG_ON(!dentry); hidden_dentry = au_h_dptr_i(dentry, bindex); DEBUG_ON(!hidden_dentry); hidden_inode = hidden_dentry->d_inode; DEBUG_ON(!hidden_inode); sb = dentry->d_sb; udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY); if (unlikely(udba)) { // test here? } br = stobr(sb, bindex); br_get(br); /* drop flags for writing */ if (test_ro(sb, bindex, dentry->d_inode)) flags = au_file_roflags(flags); flags &= ~O_CREAT; spin_lock(&hidden_inode->i_lock); old_size = i_size_read(hidden_inode); spin_unlock(&hidden_inode->i_lock); //DbgSleep(3); dget(hidden_dentry); hidden_mnt = mntget(br->br_mnt); hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags); //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);} if (!IS_ERR(hidden_file)) { #if 0 // remove this if (/* old_size && */ (flags & O_TRUNC)) { au_direval_dec(dentry); if (!IS_ROOT(dentry)) au_direval_dec(dentry->d_parent); } #endif return hidden_file; } br_put(br); TraceErrPtr(hidden_file); return hidden_file; }
static int autofs4_dir_open(struct inode *inode, struct file *file) { struct dentry *dentry = file->f_dentry; struct vfsmount *mnt = file->f_vfsmnt; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); int status; DPRINTK("file=%p dentry=%p %.*s", file, dentry, dentry->d_name.len, dentry->d_name.name); if (autofs4_oz_mode(sbi)) goto out; if (autofs4_ispending(dentry)) { DPRINTK("dentry busy"); return -EBUSY; } if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { struct nameidata nd; int empty; /* In case there are stale directory dentrys from a failed mount */ spin_lock(&dcache_lock); empty = list_empty(&dentry->d_subdirs); spin_unlock(&dcache_lock); if (!empty) d_invalidate(dentry); nd.flags = LOOKUP_DIRECTORY; status = (dentry->d_op->d_revalidate)(dentry, &nd); if (!status) return -ENOENT; } if (d_mountpoint(dentry)) { struct file *fp = NULL; struct vfsmount *fp_mnt = mntget(mnt); struct dentry *fp_dentry = dget(dentry); while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry)); fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); status = PTR_ERR(fp); if (IS_ERR(fp)) { file->private_data = NULL; return status; } file->private_data = fp; } out: return 0; }
struct file *unionfs_dentry_open(struct dentry *ptr, struct vfsmount *mnt, int flags, int line, const char *file) { atomic_inc(&unionfs_dget_counter); if (ptr) atomic_dec(&unionfs_dgets_outstanding); printk("DO:%d:%d:%d:%p:%d:%s\n", atomic_read(&unionfs_dget_counter), atomic_read(&unionfs_dgets_outstanding), ptr ? atomic_read(&ptr->d_count) : 0, ptr, line, file); return dentry_open(ptr, mnt, flags); }
/* * ima_calc_file_hash - calculate file hash * * Asynchronous hash (ahash) allows using HW acceleration for calculating * a hash. ahash performance varies for different data sizes on different * crypto accelerators. shash performance might be better for smaller files. * The 'ima.ahash_minsize' module parameter allows specifying the best * minimum file size for using ahash on the system. * * If the ima.ahash_minsize parameter is not specified, this function uses * shash for the hash calculation. If ahash fails, it falls back to using * shash. */ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) { loff_t i_size; int rc; struct file *f = file; bool new_file_instance = false, modified_flags = false; /* * For consistency, fail file's opened with the O_DIRECT flag on * filesystems mounted with/without DAX option. */ if (file->f_flags & O_DIRECT) { hash->length = hash_digest_size[ima_hash_algo]; hash->algo = ima_hash_algo; return -EINVAL; } /* Open a new file instance in O_RDONLY if we cannot read */ if (!(file->f_mode & FMODE_READ)) { int flags = file->f_flags & ~(O_WRONLY | O_APPEND | O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL); flags |= O_RDONLY; f = dentry_open(&file->f_path, flags, file->f_cred); if (IS_ERR(f)) { /* * Cannot open the file again, lets modify f_flags * of original and continue */ pr_info_ratelimited("Unable to reopen file for reading.\n"); f = file; f->f_flags |= FMODE_READ; modified_flags = true; } else { new_file_instance = true; } } i_size = i_size_read(file_inode(f)); if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { rc = ima_calc_file_ahash(f, hash); if (!rc) goto out; } rc = ima_calc_file_shash(f, hash); out: if (new_file_instance) fput(f); else if (modified_flags) f->f_flags &= ~FMODE_READ; return rc; }
static int __open_file(struct inode *inode, struct file *file, struct dentry *parent) { struct dentry *lower_dentry; struct file *lower_file; struct vfsmount *lower_mnt; struct dentry *dentry = file->f_path.dentry; int lower_flags; int i = 0, idx = 0; for (i = 0; i <= 1; i++) { lower_dentry = wrapfs_lower_dentry_idx(dentry, i); if (!lower_dentry || !lower_dentry->d_inode) continue; lower_flags = file->f_flags; if (lower_dentry->d_inode && (i == 1)) { UDBG; if (lower_flags & O_TRUNC) { int size = 0; int err = -EROFS; UDBG; err = copyup_file(parent->d_inode, file, i, 0, size); if (!err) break; return err; } else lower_flags &= ~(OPEN_WRITE_FLAGS); } dget(lower_dentry); lower_mnt = mntget(wrapfs_lower_mnt_idx(dentry, i)); if (!lower_mnt) lower_mnt = mntget(wrapfs_lower_mnt_idx(parent, i)); lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags, current_cred()); if (IS_ERR(lower_file)) return PTR_ERR(lower_file); wrapfs_set_lower_file(file, lower_file); branchget(inode->i_sb, i); idx = i; goto out; } out: if (!wrapfs_lower_inode_idx(inode, idx)) fsstack_copy_attr_all(inode, wrapfs_lower_inode_idx(inode, idx)); return 0; }
struct file *vfsub_dentry_open(struct path *path, int flags) { struct file *file; file = dentry_open(path, flags /* | __FMODE_NONOTIFY */, current_cred()); if (!IS_ERR_OR_NULL(file) && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) i_readcount_inc(path->dentry->d_inode); return file; }
struct file *vfsub_dentry_open(struct path *path, int flags, const struct cred *cred) { struct file *file; file = dentry_open(path->dentry, path->mnt, flags, cred); if (IS_ERR(file)) return file; /* as NFSD does, just call ima_..._get() simply after dentry_open */ ima_counts_get(file); return file; }
/* * look for case-insensitive matching entry name. * Returns : * - char * of matching entry if found. * - NULL if no matching entry * - ERR_PTR on error * */ static void * find_case_insensitive(struct path * lower_parent_path, const char * name) { void * ret = NULL; struct file *lower_dirp = NULL; struct sdcardfs_dirent dirent; int err; /* * At the end of this function, filp_close or dentry_open (if fails) * will decrease refernce count of lower_parent_path. * (ie, path->dentry->d_count and path->mnt->mnt_count) * To prevent those counter from dropping to zero, * we increase the counters in advance. */ path_get(lower_parent_path); lower_dirp = dentry_open(lower_parent_path->dentry, lower_parent_path->mnt, O_RDONLY, current_cred()); if (IS_ERR(lower_dirp)) { return (void *)lower_dirp; } while (1) { err = sdcardfs_getdents(lower_dirp, &dirent); if (likely(err > 0)) { /* we got a direntry */ if (unlikely(!strcasecmp(dirent.d_name, name))) { int len; len = strlen(dirent.d_name) + 1; ret = kmalloc(len, GFP_KERNEL); if (ret == NULL) ret = ERR_PTR(-ENOMEM); else strcpy(ret, dirent.d_name); break; } } else if (err == 0) { /* end of directory */ ret = NULL; break; } else { /* err < 0 : error */ ret = ERR_PTR(err); break; } } filp_close(lower_dirp, NULL); return ret; }
/* Note: dput(dchild) will *not* be called if there is an error */ struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de, int flags) { struct path path = { .dentry = de, .mnt = ctxt->pwdmnt, }; return dentry_open(&path, flags, current_cred()); } EXPORT_SYMBOL(l_dentry_open); #ifdef LPROCFS __s64 lprocfs_read_helper(struct lprocfs_counter *lc, struct lprocfs_counter_header *header, enum lprocfs_stats_flags flags, enum lprocfs_fields_flags field) { __s64 ret = 0; if (lc == NULL || header == NULL) return 0; switch (field) { case LPROCFS_FIELDS_FLAGS_CONFIG: ret = header->lc_config; break; case LPROCFS_FIELDS_FLAGS_SUM: ret = lc->lc_sum; if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) ret += lc->lc_sum_irq; break; case LPROCFS_FIELDS_FLAGS_MIN: ret = lc->lc_min; break; case LPROCFS_FIELDS_FLAGS_MAX: ret = lc->lc_max; break; case LPROCFS_FIELDS_FLAGS_AVG: ret = (lc->lc_max - lc->lc_min) / 2; break; case LPROCFS_FIELDS_FLAGS_SUMSQUARE: ret = lc->lc_sumsquare; break; case LPROCFS_FIELDS_FLAGS_COUNT: ret = lc->lc_count; break; default: break; } return ret; }
/** * get_name - default export_operations->get_name function * @dentry: the directory in which to find a name * @name: a pointer to a %NAME_MAX+1 char buffer to store the name * @child: the dentry for the child directory. * * calls readdir on the parent until it finds an entry with * the same inode number as the child, and returns that. */ static int get_name(struct dentry *dentry, char *name, struct dentry *child) { struct inode *dir = dentry->d_inode; int error; struct file *file; struct getdents_callback buffer; error = -ENOTDIR; if (!dir || !S_ISDIR(dir->i_mode)) goto out; error = -EINVAL; if (!dir->i_fop) goto out; /* * Open the directory ... */ file = dentry_open(dget(dentry), NULL, O_RDONLY); error = PTR_ERR(file); if (IS_ERR(file)) goto out; error = -EINVAL; if (!file->f_op->readdir) goto out_close; buffer.name = name; buffer.ino = child->d_inode->i_ino; buffer.found = 0; buffer.sequence = 0; while (1) { int old_seq = buffer.sequence; error = vfs_readdir(file, filldir_one, &buffer); if (error < 0) break; error = 0; if (buffer.found) break; error = -ENOENT; if (old_seq == buffer.sequence) break; } out_close: fput(file); out: return error; }
static int wrapfs_open(struct inode *inode, struct file *file) { int err = 0; struct file *lower_file = NULL; struct path lower_path; #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_MESG("Enter"); #endif /* don't open unhashed/deleted files */ if (d_unhashed(file->f_path.dentry)) { err = -ENOENT; goto out_err; } file->private_data = kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL); if (!WRAPFS_F(file)) { err = -ENOMEM; goto out_err; } /* open lower object and link wrapfs's file struct to lower's */ wrapfs_get_lower_path(file->f_path.dentry, &lower_path); lower_file = dentry_open(lower_path.dentry, lower_path.mnt, file->f_flags, current_cred()); if (IS_ERR(lower_file)) { err = PTR_ERR(lower_file); lower_file = wrapfs_lower_file(file); if (lower_file) { wrapfs_set_lower_file(file, NULL); fput(lower_file); /* fput calls dput for lower_dentry */ } } else { wrapfs_set_lower_file(file, lower_file); } if (err) kfree(WRAPFS_F(file)); else fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode)); out_err: #ifdef EXTRA_CREDIT if(wrapfs_get_debug(file->f_dentry->d_sb) & DEBUG_FILE) DEBUG_RETURN("Exit", err); #endif return err; }
/* * Note that a shared library must be both readable and executable due to * security reasons. * * Also note that we take the address to load from from the file itself. */ asmlinkage long sys_uselib(const char __user * library) { struct file * file; struct nameidata nd; int error; nd.intent.open.flags = FMODE_READ; error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); if (error) goto out; error = -EINVAL; if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); if (error) goto exit; file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); error = PTR_ERR(file); if (IS_ERR(file)) goto out; error = -ENOEXEC; if(file->f_op) { struct linux_binfmt * fmt; read_lock(&binfmt_lock); for (fmt = formats ; fmt ; fmt = fmt->next) { if (!fmt->load_shlib) continue; if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); error = fmt->load_shlib(file); read_lock(&binfmt_lock); put_binfmt(fmt); if (error != -ENOEXEC) break; } read_unlock(&binfmt_lock); } fput(file); out: return error; exit: path_release(&nd); goto out; }
/* open the highest priority file for a given upper file */ static int open_highest_file(struct file *file, bool willwrite) { int bindex, bstart, bend, err = 0; struct file *lower_file; struct dentry *lower_dentry; struct dentry *dentry = file->f_path.dentry; struct dentry *parent = dget_parent(dentry); struct inode *parent_inode = parent->d_inode; struct super_block *sb = dentry->d_sb; bstart = dbstart(dentry); bend = dbend(dentry); lower_dentry = unionfs_lower_dentry(dentry); if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) { for (bindex = bstart - 1; bindex >= 0; bindex--) { err = copyup_file(parent_inode, file, bstart, bindex, i_size_read(dentry->d_inode)); if (!err) break; } atomic_set(&UNIONFS_F(file)->generation, atomic_read(&UNIONFS_I(dentry->d_inode)-> generation)); goto out; } dget(lower_dentry); unionfs_mntget(dentry, bstart); lower_file = dentry_open(lower_dentry, unionfs_lower_mnt_idx(dentry, bstart), file->f_flags, current_cred()); if (IS_ERR(lower_file)) { err = PTR_ERR(lower_file); goto out; } branchget(sb, bstart); unionfs_set_lower_file(file, lower_file); /* Fix up the position. */ lower_file->f_pos = file->f_pos; memcpy(&lower_file->f_ra, &file->f_ra, sizeof(struct file_ra_state)); out: dput(parent); return err; }
/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ struct file *filp_open(const char * filename, int flags, int mode) { int namei_flags, error; struct nameidata nd; namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) namei_flags++; if (namei_flags & O_TRUNC) namei_flags |= 2; error = open_namei(filename, namei_flags, mode, &nd); if (!error) return dentry_open(nd.dentry, nd.mnt, flags); return ERR_PTR(error); }
struct file *vfsub_dentry_open(struct path *path, int flags) { struct file *file; int err; path_get(path); file = dentry_open(path->dentry, path->mnt, flags, current_cred()); if (IS_ERR(file)) goto out; err = ima_file_check(file, au_conv_oflags(flags)); if (unlikely(err)) { fput(file); file = ERR_PTR(err); } out: return file; }