X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=libcfs%2Flibcfs%2Flinux%2Flinux-curproc.c;h=70510c990c9679c5625a7fea0878a457ef5aac12;hb=4f18daa42192090b135606816bcb3a6dd8777f0a;hp=c1e814d7132d067477d10d74a14e0fb867ed551f;hpb=f641913a348ec0179cdc599baa93f74aa64f9943;p=fs%2Flustre-release.git diff --git a/libcfs/libcfs/linux/linux-curproc.c b/libcfs/libcfs/linux/linux-curproc.c index c1e814d..70510c9 100644 --- a/libcfs/libcfs/linux/linux-curproc.c +++ b/libcfs/libcfs/linux/linux-curproc.c @@ -15,17 +15,15 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, 2017, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -39,8 +37,12 @@ */ #include +#ifdef HAVE_SCHED_HEADERS +#include +#include +#endif #include - +#include #include #include @@ -53,103 +55,11 @@ * for Linux kernel. */ -uid_t cfs_curproc_uid(void) -{ - return current_uid(); -} - -gid_t cfs_curproc_gid(void) -{ - return current_gid(); -} - -uid_t cfs_curproc_fsuid(void) -{ - return current_fsuid(); -} - -uid_t cfs_curproc_euid(void) -{ - return current_euid(); -} - -uid_t cfs_curproc_egid(void) -{ - return current_egid(); -} - -gid_t cfs_curproc_fsgid(void) -{ - return current_fsgid(); -} - -pid_t cfs_curproc_pid(void) -{ - return current->pid; -} - -int cfs_curproc_groups_nr(void) -{ - int nr; - - task_lock(current); - nr = current_cred()->group_info->ngroups; - task_unlock(current); - return nr; -} - -void cfs_curproc_groups_dump(gid_t *array, int size) -{ - task_lock(current); - size = min_t(int, size, current_cred()->group_info->ngroups); - memcpy(array, current_cred()->group_info->blocks[0], size * sizeof(__u32)); - task_unlock(current); -} - - -int cfs_curproc_is_in_groups(gid_t gid) -{ - return in_group_p(gid); -} - -mode_t cfs_curproc_umask(void) -{ - return current->fs->umask; -} - -char *cfs_curproc_comm(void) -{ - return current->comm; -} - /* Currently all the CFS_CAP_* defines match CAP_* ones. */ #define cfs_cap_pack(cap) (cap) #define cfs_cap_unpack(cap) (cap) -void cfs_cap_raise(cfs_cap_t cap) -{ - struct cred *cred; - if ((cred = prepare_creds())) { - cap_raise(cred->cap_effective, cfs_cap_unpack(cap)); - commit_creds(cred); - } -} - -void cfs_cap_lower(cfs_cap_t cap) -{ - struct cred *cred; - if ((cred = prepare_creds())) { - cap_lower(cred->cap_effective, cfs_cap_unpack(cap)); - commit_creds(cred); - } -} - -int cfs_cap_raised(cfs_cap_t cap) -{ - return cap_raised(current_cap(), cfs_cap_unpack(cap)); -} - -void cfs_kernel_cap_pack(cfs_kernel_cap_t kcap, cfs_cap_t *cap) +static void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap) { #if defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x19980330 *cap = cfs_cap_pack(kcap); @@ -163,7 +73,7 @@ void cfs_kernel_cap_pack(cfs_kernel_cap_t kcap, cfs_cap_t *cap) #endif } -void cfs_kernel_cap_unpack(cfs_kernel_cap_t *kcap, cfs_cap_t cap) +static void cfs_kernel_cap_unpack(kernel_cap_t *kcap, cfs_cap_t cap) { #if defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x19980330 *kcap = cfs_cap_unpack(cap); @@ -197,48 +107,37 @@ int cfs_capable(cfs_cap_t cap) return capable(cfs_cap_unpack(cap)); } -/* Check if task is running in 32-bit API mode, for the purpose of - * userspace binary interfaces. On 32-bit Linux this is (unfortunately) - * always true, even if the application is using LARGEFILE64 and 64-bit - * APIs, because Linux provides no way for the filesystem to know if it - * is called via 32-bit or 64-bit APIs. Other clients may vary. On - * 64-bit systems, this will only be true if the binary is calling a - * 32-bit system call. */ -int cfs_curproc_is_32bit(void) -{ -#ifdef HAVE_IS_COMPAT_TASK - return is_compat_task(); -#else - return (BITS_PER_LONG == 32); -#endif -} - -static int cfs_access_process_vm(struct task_struct *tsk, unsigned long addr, +static int cfs_access_process_vm(struct task_struct *tsk, + struct mm_struct *mm, + unsigned long addr, void *buf, int len, int write) { -#ifdef HAVE_ACCESS_PROCESS_VM - return access_process_vm(tsk, addr, buf, len, write); -#else /* Just copied from kernel for the kernels which doesn't * have access_process_vm() exported */ - struct mm_struct *mm; struct vm_area_struct *vma; struct page *page; void *old_buf = buf; - mm = get_task_mm(tsk); - if (!mm) - return 0; + /* Avoid deadlocks on mmap_sem if called from sys_mmap_pgoff(), + * which is already holding mmap_sem for writes. If some other + * thread gets the write lock in the meantime, this thread will + * block, but at least it won't deadlock on itself. LU-1735 */ + if (down_read_trylock(&mm->mmap_sem) == 0) + return -EDEADLK; - down_read(&mm->mmap_sem); - /* ignore errors, just check how much was sucessfully transfered */ + /* ignore errors, just check how much was successfully transferred */ while (len) { - int bytes, ret, offset; + int bytes, rc, offset; void *maddr; - ret = get_user_pages(tsk, mm, addr, 1, - write, 1, &page, &vma); - if (ret <= 0) +#if defined(HAVE_GET_USER_PAGES_GUP_FLAGS) + rc = get_user_pages(addr, 1, write ? FOLL_WRITE : 0, &page, &vma); +#elif defined(HAVE_GET_USER_PAGES_6ARG) + rc = get_user_pages(addr, 1, write, 1, &page, &vma); +#else + rc = get_user_pages(tsk, mm, addr, 1, write, 1, &page, &vma); +#endif + if (rc <= 0) break; bytes = len; @@ -256,59 +155,51 @@ static int cfs_access_process_vm(struct task_struct *tsk, unsigned long addr, buf, maddr + offset, bytes); } kunmap(page); - page_cache_release(page); + put_page(page); len -= bytes; buf += bytes; addr += bytes; } up_read(&mm->mmap_sem); - mmput(mm); return buf - old_buf; -#endif /* HAVE_ACCESS_PROCESS_VM */ } /* Read the environment variable of current process specified by @key. */ int cfs_get_environ(const char *key, char *value, int *val_len) { struct mm_struct *mm; - char *buffer, *tmp_buf = NULL; - int buf_len = CFS_PAGE_SIZE; + char *buffer; + int buf_len = PAGE_SIZE; + int key_len = strlen(key); unsigned long addr; - int ret; + int rc; + bool skip = false; ENTRY; - buffer = (char *)cfs_alloc(buf_len, CFS_ALLOC_USER); + buffer = kmalloc(buf_len, GFP_USER); if (!buffer) RETURN(-ENOMEM); mm = get_task_mm(current); if (!mm) { - cfs_free((void *)buffer); + kfree(buffer); RETURN(-EINVAL); } - /* Avoid deadlocks on mmap_sem if called from sys_mmap_pgoff(), - * which is already holding mmap_sem for writes. If some other - * thread gets the write lock in the meantime, this thread will - * block, but at least it won't deadlock on itself. LU-1735 */ - if (down_read_trylock(&mm->mmap_sem) == 0) - return -EDEADLK; - up_read(&mm->mmap_sem); - addr = mm->env_start; - ret = -ENOENT; - while (addr < mm->env_end) { int this_len, retval, scan_len; char *env_start, *env_end; memset(buffer, 0, buf_len); - this_len = min((int)(mm->env_end - addr), buf_len); - retval = cfs_access_process_vm(current, addr, buffer, + this_len = min_t(int, mm->env_end - addr, buf_len); + retval = cfs_access_process_vm(current, mm, addr, buffer, this_len, 0); - if (retval != this_len) + if (retval < 0) + GOTO(out, rc = retval); + else if (retval != this_len) break; addr += retval; @@ -321,77 +212,62 @@ int cfs_get_environ(const char *key, char *value, int *val_len) char *entry; int entry_len; - env_end = (char *)memscan(env_start, '\0', scan_len); + env_end = memscan(env_start, '\0', scan_len); LASSERT(env_end >= env_start && env_end <= env_start + scan_len); /* The last entry of this buffer cross the buffer * boundary, reread it in next cycle. */ if (unlikely(env_end - env_start == scan_len)) { - /* This entry is too large to fit in buffer */ - if (unlikely(scan_len == this_len)) { - CERROR("Too long env variable.\n"); - ret = -EINVAL; - goto out; - } - addr -= scan_len; + /* Just skip the entry larger than page size, + * it can't be jobID env variable. */ + if (unlikely(scan_len == this_len)) + skip = true; + else + addr -= scan_len; break; + } else if (unlikely(skip)) { + skip = false; + goto skip; } entry = env_start; entry_len = env_end - env_start; /* Key length + length of '=' */ - if (entry_len > strlen(key) + 1 && - !memcmp(entry, key, strlen(key))) { - entry += (strlen(key) + 1); - entry_len -= (strlen(key) + 1); - /* The 'value' buffer passed in is too small.*/ + if (entry_len > key_len + 1 && + !memcmp(entry, key, key_len)) { + entry += key_len + 1; + entry_len -= key_len + 1; + + /* The 'value' buffer passed in is too small. + * Copy what fits, but return -EOVERFLOW. */ if (entry_len >= *val_len) { - CERROR("Buffer is too small. " - "entry_len=%d buffer_len=%d\n", - entry_len, *val_len); - ret = -EOVERFLOW; - } else { - memcpy(value, entry, entry_len); - *val_len = entry_len; - ret = 0; + memcpy(value, entry, *val_len); + value[*val_len - 1] = 0; + GOTO(out, rc = -EOVERFLOW); } - goto out; - } + memcpy(value, entry, entry_len); + *val_len = entry_len; + GOTO(out, rc = 0); + } +skip: scan_len -= (env_end - env_start + 1); env_start = env_end + 1; } } + GOTO(out, rc = -ENOENT); + out: mmput(mm); - cfs_free((void *)buffer); - if (tmp_buf) - cfs_free((void *)tmp_buf); - RETURN(ret); + kfree((void *)buffer); + return rc; } EXPORT_SYMBOL(cfs_get_environ); -EXPORT_SYMBOL(cfs_curproc_uid); -EXPORT_SYMBOL(cfs_curproc_pid); -EXPORT_SYMBOL(cfs_curproc_euid); -EXPORT_SYMBOL(cfs_curproc_gid); -EXPORT_SYMBOL(cfs_curproc_egid); -EXPORT_SYMBOL(cfs_curproc_fsuid); -EXPORT_SYMBOL(cfs_curproc_fsgid); -EXPORT_SYMBOL(cfs_curproc_umask); -EXPORT_SYMBOL(cfs_curproc_comm); -EXPORT_SYMBOL(cfs_curproc_groups_nr); -EXPORT_SYMBOL(cfs_curproc_groups_dump); -EXPORT_SYMBOL(cfs_curproc_is_in_groups); -EXPORT_SYMBOL(cfs_cap_raise); -EXPORT_SYMBOL(cfs_cap_lower); -EXPORT_SYMBOL(cfs_cap_raised); EXPORT_SYMBOL(cfs_curproc_cap_pack); -EXPORT_SYMBOL(cfs_curproc_cap_unpack); EXPORT_SYMBOL(cfs_capable); -EXPORT_SYMBOL(cfs_curproc_is_32bit); /* * Local variables: