struct dentry *lzfs_get_parent(struct dentry *child) { vnode_t *vcp = LZFS_ITOV(child->d_inode); vnode_t *vp; int error = 0; struct dentry *dentry = NULL; const struct cred *cred = get_current_cred(); SENTRY; error = zfs_lookup(vcp, "..", &vp, NULL, 0 , NULL, (struct cred *) cred, NULL, NULL, NULL); put_cred(cred); tsd_exit(); SEXIT; if (error) { if (error == ENOENT) { printk(KERN_WARNING "Try to get new dentry \n"); return d_splice_alias(NULL, dentry); } else { printk(KERN_WARNING "Unable to get dentry \n"); return ERR_PTR(-error); } } if (LZFS_VTOI(vp)) dentry = d_obtain_alias(LZFS_VTOI(vp)); return dentry; }
MTK_WCN_BOOL wmt_dev_is_file_exist(PUINT8 pFileName) { struct file *fd = NULL; /* ssize_t iRet; */ INT32 fileLen = -1; const struct cred *cred = get_current_cred(); if (pFileName == NULL) { WMT_ERR_FUNC("invalid file name pointer(%p)\n", pFileName); return MTK_WCN_BOOL_FALSE; } if (osal_strlen(pFileName) < osal_strlen(defaultPatchName)) { WMT_ERR_FUNC("invalid file name(%s)\n", pFileName); return MTK_WCN_BOOL_FALSE; } /* struct cred *cred = get_task_cred(current); */ fd = filp_open(pFileName, O_RDONLY, 0); if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { WMT_ERR_FUNC("failed to open or read(%s)!(0x%p, %d, %d)\n", pFileName, fd, cred->fsuid, cred->fsgid); return MTK_WCN_BOOL_FALSE; } fileLen = fd->f_path.dentry->d_inode->i_size; filp_close(fd, NULL); fd = NULL; if (fileLen <= 0) { WMT_ERR_FUNC("invalid file(%s), length(%d)\n", pFileName, fileLen); return MTK_WCN_BOOL_FALSE; } WMT_ERR_FUNC("valid file(%s), length(%d)\n", pFileName, fileLen); return true; }
static int appcl_mask_perm_check(struct inode *inode, int mask) { struct inode_security_label *ilabel; const char *d_behaviour = APPCL_DEFAULT_ALLOW; const struct cred *c_cred; ilabel = inode->i_security; if (!ilabel || !mask) return 0; /* * Fetch current credential and default behaviour state */ c_cred = get_current_cred(); validate_creds(c_cred); d_behaviour = ilabel->d_behaviour; if (unlikely(IS_PRIVATE(inode))) return 0; rcu_read_lock(); mutex_lock(&ilabel->lock); /* * Check current credential path against inode 'PACL' entries */ if (check_inode_path_match(inode, c_cred)) { /* * Check requested permission mask against inode 'PACL' entries */ if (appcl_check_permission_mask_match(ilabel, c_cred, mask)) goto successout; else goto failout; } else { /* * Checks DENY default behaviour * Return -EACCES if true */ if (strncmp(d_behaviour, APPCL_DEFAULT_DENY, LOWERVALUELEN) == 0) goto failout; else goto successout; } successout: rcu_read_unlock(); mutex_unlock(&ilabel->lock); put_cred(c_cred); return 0; failout: rcu_read_unlock(); mutex_unlock(&ilabel->lock); put_cred(c_cred); return -EACCES; }
/** * alloc_fs_context - Create a filesystem context. * @fs_type: The filesystem type. * @reference: The dentry from which this one derives (or NULL) * @sb_flags: Filesystem/superblock flags (SB_*) * @sb_flags_mask: Applicable members of @sb_flags * @purpose: The purpose that this configuration shall be used for. * * Open a filesystem and create a mount context. The mount context is * initialised with the supplied flags and, if a submount/automount from * another superblock (referred to by @reference) is supplied, may have * parameters such as namespaces copied across from that superblock. */ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type, struct dentry *reference, unsigned int sb_flags, unsigned int sb_flags_mask, enum fs_context_purpose purpose) { int (*init_fs_context)(struct fs_context *); struct fs_context *fc; int ret = -ENOMEM; fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL); if (!fc) return ERR_PTR(-ENOMEM); fc->purpose = purpose; fc->sb_flags = sb_flags; fc->sb_flags_mask = sb_flags_mask; fc->fs_type = get_filesystem(fs_type); fc->cred = get_current_cred(); fc->net_ns = get_net(current->nsproxy->net_ns); mutex_init(&fc->uapi_mutex); switch (purpose) { case FS_CONTEXT_FOR_MOUNT: fc->user_ns = get_user_ns(fc->cred->user_ns); break; case FS_CONTEXT_FOR_SUBMOUNT: fc->user_ns = get_user_ns(reference->d_sb->s_user_ns); break; case FS_CONTEXT_FOR_RECONFIGURE: /* We don't pin any namespaces as the superblock's * subscriptions cannot be changed at this point. */ atomic_inc(&reference->d_sb->s_active); fc->root = dget(reference); break; } /* TODO: Make all filesystems support this unconditionally */ init_fs_context = fc->fs_type->init_fs_context; if (!init_fs_context) init_fs_context = legacy_init_fs_context; ret = init_fs_context(fc); if (ret < 0) goto err_fc; fc->need_free = true; return fc; err_fc: put_fs_context(fc); return ERR_PTR(ret); }
STATIC int linvfs_open( struct inode *inode, struct file *filp) { vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *newvp; int error; ASSERT(vp); VOP_OPEN(vp, &newvp, 0, get_current_cred(), error); return -error; }
STATIC long long linvfs_file_lseek( struct file *file, loff_t offset, int origin) { struct inode *inode = file->f_dentry->d_inode; vnode_t *vp; struct vattr vattr; loff_t old_off = offset; int error; vp = LINVFS_GET_VP(inode); ASSERT(vp); switch (origin) { case 2: vattr.va_mask = AT_SIZE; VOP_GETATTR(vp, &vattr, 0, get_current_cred(), error); if (error) return -error; offset += vattr.va_size; break; case 1: offset += file->f_pos; } /* All for the sake of seeing if we are too big */ VOP_SEEK(vp, old_off, &offset, error); if (error) return -error; if (offset != file->f_pos) { file->f_pos = offset; file->f_version = ++event; file->f_reada = 0; } return offset; }
cred_t * crref(void) { #if defined(STRUCT_TASK_STRUCT_HAS_CRED) return (cred_t *)get_current_cred(); #else cred_t *cr = crget(); afs_set_cr_uid(cr, current_fsuid()); afs_set_cr_ruid(cr, current_uid()); afs_set_cr_gid(cr, current_fsgid()); afs_set_cr_rgid(cr, current_gid()); task_lock(current); get_group_info(current_group_info()); afs_set_cr_group_info(cr, current_group_info()); task_unlock(current); return cr; #endif }
/* * This function decides whether to allow an operation * * The operation can be one of the following values: * 0 - Execute (run the "file" - meaningless in our case) * 2 - Write (input to the kernel module) * 4 - Read (output from the kernel module) * * Return: * 0 allowed * non-zero not allowed */ static int module_permission(struct inode *inode, int op) { int ret = -EACCES; const struct cred *cred; /* We allow everybody to read from our module, but * only root (uid 0) may write to it */ if (op & MAY_READ) ret = 0; if (op & MAY_WRITE) { cred = get_current_cred(); if (cred->euid == 0) ret = 0; else ret = -EACCES; put_cred(cred); } return ret; }
STATIC int linvfs_fsync( struct file *filp, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); int error; int flags = FSYNC_WAIT; if (datasync) flags |= FSYNC_DATA; ASSERT(vp); VOP_FSYNC(vp, flags, get_current_cred(), (off_t)0, (off_t)-1, error); if (error) return -error; return 0; }
struct sock *__vsock_create(struct net *net, struct socket *sock, struct sock *parent, gfp_t priority, unsigned short type, int kern) { struct sock *sk; struct vsock_sock *psk; struct vsock_sock *vsk; sk = sk_alloc(net, AF_VSOCK, priority, &vsock_proto, kern); if (!sk) return NULL; sock_init_data(sock, sk); /* sk->sk_type is normally set in sock_init_data, but only if sock is * non-NULL. We make sure that our sockets always have a type by * setting it here if needed. */ if (!sock) sk->sk_type = type; vsk = vsock_sk(sk); vsock_addr_init(&vsk->local_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); vsock_addr_init(&vsk->remote_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); sk->sk_destruct = vsock_sk_destruct; sk->sk_backlog_rcv = vsock_queue_rcv_skb; sock_reset_flag(sk, SOCK_DONE); INIT_LIST_HEAD(&vsk->bound_table); INIT_LIST_HEAD(&vsk->connected_table); vsk->listener = NULL; INIT_LIST_HEAD(&vsk->pending_links); INIT_LIST_HEAD(&vsk->accept_queue); vsk->rejected = false; vsk->sent_request = false; vsk->ignore_connecting_rst = false; vsk->peer_shutdown = 0; psk = parent ? vsock_sk(parent) : NULL; if (parent) { vsk->trusted = psk->trusted; vsk->owner = get_cred(psk->owner); vsk->connect_timeout = psk->connect_timeout; } else { vsk->trusted = capable(CAP_NET_ADMIN); vsk->owner = get_current_cred(); vsk->connect_timeout = VSOCK_DEFAULT_CONNECT_TIMEOUT; } if (transport->init(vsk, psk) < 0) { sk_free(sk); return NULL; } if (sock) vsock_insert_unbound(vsk); return sk; }
// TODO: [ChangeFeature][George] refine this function name for general filesystem read operation, not patch only. INT32 wmt_dev_patch_get ( UCHAR *pPatchName, osal_firmware **ppPatch, INT32 padSzBuf ) { INT32 iRet = -1; osal_firmware *pfw; uid_t orig_uid; gid_t orig_gid; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) //struct cred *cred = get_task_cred(current); struct cred *cred = (struct cred *)get_current_cred(); #endif mm_segment_t orig_fs = get_fs(); if (*ppPatch) { WMT_WARN_FUNC("f/w patch already exists \n"); if ((*ppPatch)->data) { vfree((*ppPatch)->data); } kfree(*ppPatch); *ppPatch = NULL; } if (!osal_strlen(pPatchName)) { WMT_ERR_FUNC("empty f/w name\n"); osal_assert((osal_strlen(pPatchName) > 0)); return -1; } pfw = kzalloc(sizeof(osal_firmware), /*GFP_KERNEL*/GFP_ATOMIC); if (!pfw) { WMT_ERR_FUNC("kzalloc(%d) fail\n", sizeof(osal_firmware)); return -2; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) orig_uid = cred->fsuid; orig_gid = cred->fsgid; cred->fsuid = cred->fsgid = 0; #else orig_uid = current->fsuid; orig_gid = current->fsgid; current->fsuid = current->fsgid = 0; #endif set_fs(get_ds()); /* load patch file from fs */ iRet = wmt_dev_read_file(pPatchName, &pfw->data, 0, padSzBuf); set_fs(orig_fs); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) cred->fsuid = orig_uid; cred->fsgid = orig_gid; #else current->fsuid = orig_uid; current->fsgid = orig_gid; #endif if (iRet > 0) { pfw->size = iRet; *ppPatch = pfw; WMT_DBG_FUNC("load (%s) to addr(0x%p) success\n", pPatchName, pfw->data); return 0; } else { kfree(pfw); *ppPatch = NULL; WMT_ERR_FUNC("load file (%s) fail, iRet(%d) \n", pPatchName, iRet); return -1; } }
INT32 wmt_dev_read_file ( UCHAR *pName, const u8 **ppBufPtr, INT32 offset, INT32 padSzBuf ) { INT32 iRet = -1; struct file *fd; //ssize_t iRet; INT32 file_len; INT32 read_len; void *pBuf; //struct cred *cred = get_task_cred(current); const struct cred *cred = get_current_cred(); if (!ppBufPtr ) { WMT_ERR_FUNC("invalid ppBufptr!\n"); return -1; } *ppBufPtr = NULL; fd = filp_open(pName, O_RDONLY, 0); if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { WMT_ERR_FUNC("failed to open or read!(0x%p, %d, %d)\n", fd, cred->fsuid, cred->fsgid); return -1; } file_len = fd->f_path.dentry->d_inode->i_size; pBuf = vmalloc((file_len + BCNT_PATCH_BUF_HEADROOM + 3) & ~0x3UL); if (!pBuf) { WMT_ERR_FUNC("failed to vmalloc(%d)\n", (INT32)((file_len + 3) & ~0x3UL)); goto read_file_done; } do { if (fd->f_pos != offset) { if (fd->f_op->llseek) { if (fd->f_op->llseek(fd, offset, 0) != offset) { WMT_ERR_FUNC("failed to seek!!\n"); goto read_file_done; } } else { fd->f_pos = offset; } } read_len = fd->f_op->read(fd, pBuf + padSzBuf, file_len, &fd->f_pos); if (read_len != file_len) { WMT_WARN_FUNC("read abnormal: read_len(%d), file_len(%d)\n", read_len, file_len); } } while (false); iRet = 0; *ppBufPtr = pBuf; read_file_done: if (iRet) { if (pBuf) { vfree(pBuf); } } filp_close(fd, NULL); return (iRet) ? iRet : read_len; }
/* * Request userspace finish the construction of a key * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" */ static int call_sbin_request_key(struct key_construction *cons, const char *op, void *aux) { const struct cred *cred = current_cred(); key_serial_t prkey, sskey; struct key *key = cons->key, *authkey = cons->authkey, *keyring, *session; char *argv[9], *envp[3], uid_str[12], gid_str[12]; char key_str[12], keyring_str[3][12]; char desc[20]; int ret, i; kenter("{%d},{%d},%s", key->serial, authkey->serial, op); ret = install_user_keyrings(); if (ret < 0) goto error_alloc; /* allocate a new session keyring */ sprintf(desc, "_req.%u", key->serial); cred = get_current_cred(); keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, KEY_ALLOC_QUOTA_OVERRUN, NULL); put_cred(cred); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error_alloc; } /* attach the auth key to the session keyring */ ret = key_link(keyring, authkey); if (ret < 0) goto error_link; /* record the UID and GID */ sprintf(uid_str, "%d", cred->fsuid); sprintf(gid_str, "%d", cred->fsgid); /* we say which key is under construction */ sprintf(key_str, "%d", key->serial); /* we specify the process's default keyrings */ sprintf(keyring_str[0], "%d", cred->thread_keyring ? cred->thread_keyring->serial : 0); prkey = 0; if (cred->tgcred->process_keyring) prkey = cred->tgcred->process_keyring->serial; sprintf(keyring_str[1], "%d", prkey); rcu_read_lock(); session = rcu_dereference(cred->tgcred->session_keyring); if (!session) session = cred->user->session_keyring; sskey = session->serial; rcu_read_unlock(); sprintf(keyring_str[2], "%d", sskey); /* set up a minimal environment */ i = 0; envp[i++] = "HOME=/"; envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[i] = NULL; /* set up the argument list */ i = 0; argv[i++] = "/sbin/request-key"; argv[i++] = (char *) op; argv[i++] = key_str; argv[i++] = uid_str; argv[i++] = gid_str; argv[i++] = keyring_str[0]; argv[i++] = keyring_str[1]; argv[i++] = keyring_str[2]; argv[i] = NULL; /* do it */ ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, UMH_WAIT_PROC); kdebug("usermode -> 0x%x", ret); if (ret >= 0) { /* ret is the exit/wait code */ if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags) || key_validate(key) < 0) ret = -ENOKEY; else /* ignore any errors from userspace if the key was * instantiated */ ret = 0; } error_link: key_put(keyring); error_alloc: complete_request_key(cons, ret); kleave(" = %d", ret); return ret; }
static int vmci_host_do_init_context(struct vmci_host_dev *vmci_host_dev, const char *ioctl_name, void __user *uptr) { struct vmci_init_blk init_block; const struct cred *cred; int retval; if (copy_from_user(&init_block, uptr, sizeof(init_block))) { vmci_ioctl_err("error reading init block\n"); return -EFAULT; } mutex_lock(&vmci_host_dev->lock); if (vmci_host_dev->ct_type != VMCIOBJ_NOT_SET) { vmci_ioctl_err("received VMCI init on initialized handle\n"); retval = -EINVAL; goto out; } if (init_block.flags & ~VMCI_PRIVILEGE_FLAG_RESTRICTED) { vmci_ioctl_err("unsupported VMCI restriction flag\n"); retval = -EINVAL; goto out; } cred = get_current_cred(); vmci_host_dev->context = vmci_ctx_create(init_block.cid, init_block.flags, 0, vmci_host_dev->user_version, cred); put_cred(cred); if (IS_ERR(vmci_host_dev->context)) { retval = PTR_ERR(vmci_host_dev->context); vmci_ioctl_err("error initializing context\n"); goto out; } /* * Copy cid to userlevel, we do this to allow the VMX * to enforce its policy on cid generation. */ init_block.cid = vmci_ctx_get_id(vmci_host_dev->context); if (copy_to_user(uptr, &init_block, sizeof(init_block))) { vmci_ctx_destroy(vmci_host_dev->context); vmci_host_dev->context = NULL; vmci_ioctl_err("error writing init block\n"); retval = -EFAULT; goto out; } vmci_host_dev->ct_type = VMCIOBJ_CONTEXT; atomic_inc(&vmci_host_active_users); retval = 0; out: mutex_unlock(&vmci_host_dev->lock); return retval; }
static int lzfs_xattr_security_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) #endif { vnode_t *vp; vnode_t *dvp; vnode_t *xvp; vattr_t *vap; int err = 0; const struct cred *cred = get_current_cred(); struct iovec iov = { .iov_base = (void *) value, .iov_len = size, }; char *xattr_name = NULL; uio_t uio = { .uio_iov = &iov, .uio_resid = size, .uio_iovcnt = 1, .uio_loffset = (offset_t)0, .uio_limit = MAXOFFSET_T, .uio_segflg = UIO_SYSSPACE, }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) dvp = LZFS_ITOV(inode); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) dvp = LZFS_ITOV(dentry->d_inode); #endif err = zfs_lookup(dvp, NULL, &vp, NULL, LOOKUP_XATTR | CREATE_XATTR_DIR, NULL, (struct cred *) cred, NULL, NULL, NULL); if(err) { return -err; } if(!value) { err =zfs_remove(vp, (char *) name, (struct cred *)cred, NULL, 0); return -err; } vap = kmalloc(sizeof(vattr_t), GFP_KERNEL); ASSERT(vap != NULL); memset(vap, 0, sizeof(vap)); vap->va_type = VREG; vap->va_mode = 0644; vap->va_mask = AT_TYPE|AT_MODE; vap->va_uid = current_fsuid(); vap->va_gid = current_fsgid(); xattr_name = kzalloc(strlen(name) + 10, GFP_KERNEL); xattr_name = strncpy(xattr_name, "security.", 9); xattr_name = strncat(xattr_name, name, strlen(name)); err = zfs_create(vp, xattr_name, vap, 0, 0644, &xvp, (struct cred *)cred, 0, NULL, NULL); kfree(vap); kfree(xattr_name); if(err) { return -err; } err = zfs_write(xvp, &uio, 0, (cred_t *)cred, NULL); put_cred(cred); if(err) { return -err; } return -err; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) static size_t lzfs_xattr_security_list(struct inode *inode, char *list, size_t list_size, const char *name, size_t name_len) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) static size_t lzfs_xattr_security_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) #endif { const size_t total_len = name_len + 1; if (list && total_len <= list_size) { memcpy(list, name, name_len); list[name_len] = '\0'; } return total_len; } int lzfs_init_security(struct dentry *dentry, struct inode *dir) { int err; size_t len; void *value; char *name; err = security_inode_init_security(dentry->d_inode, dir, &name, &value, &len); if (err) { if (err == -EOPNOTSUPP) return 0; return err; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) err = lzfs_xattr_security_set(dentry->d_inode, name, value, len, 0); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) err = lzfs_xattr_security_set(dentry, name, value, len, 0, 0); #endif kfree(name); kfree(value); return err; } struct xattr_handler lzfs_xattr_security_handler = { .prefix = XATTR_SECURITY_PREFIX, .list = lzfs_xattr_security_list, .get = lzfs_xattr_security_get, .set = lzfs_xattr_security_set, };