X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=libcfs%2Flibcfs%2Flinux%2Flinux-curproc.c;h=fee47a23fc0a5654361607ce53c7fdda0a8256d8;hb=9776609833dff17f20c31fe727492204620b54af;hp=3a8bab70822565e04c44fb4e1d1a24462fc21839;hpb=f95393b0d0a59cf3dc2f29cffc35dcc4cc9d7728;p=fs%2Flustre-release.git diff --git a/libcfs/libcfs/linux/linux-curproc.c b/libcfs/libcfs/linux/linux-curproc.c index 3a8bab7..fee47a2 100644 --- a/libcfs/libcfs/linux/linux-curproc.c +++ b/libcfs/libcfs/linux/linux-curproc.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -17,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/ @@ -41,8 +37,12 @@ */ #include +#ifdef HAVE_SCHED_HEADERS +#include +#include +#endif #include - +#include #include #include @@ -55,85 +55,6 @@ * 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; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,4) - task_lock(current); - nr = current_cred()->group_info->ngroups; - task_unlock(current); -#else - nr = current->ngroups; -#endif - return nr; -} - -void cfs_curproc_groups_dump(gid_t *array, int size) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,4) - 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); -#else - LASSERT(size <= NGROUPS); - size = min_t(int, size, current->ngroups); - memcpy(array, current->groups, size * sizeof(__u32)); -#endif -} - - -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) @@ -161,7 +82,7 @@ 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); @@ -175,7 +96,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); @@ -209,41 +130,170 @@ 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) +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_IS_COMPAT_TASK - return is_compat_task(); + /* Just copied from kernel for the kernels which doesn't + * have access_process_vm() exported */ + struct vm_area_struct *vma; + struct page *page; + void *old_buf = buf; + + /* 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; + + /* ignore errors, just check how much was successfully transferred */ + while (len) { + int bytes, rc, offset; + void *maddr; + +#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 - return (BITS_PER_LONG == 32); + rc = get_user_pages(tsk, mm, addr, 1, write, 1, &page, &vma); #endif + if (rc <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + maddr = kmap(page); + if (write) { + copy_to_user_page(vma, page, addr, + maddr + offset, buf, bytes); + set_page_dirty_lock(page); + } else { + copy_from_user_page(vma, page, addr, + buf, maddr + offset, bytes); + } + kunmap(page); + put_page(page); + len -= bytes; + buf += bytes; + addr += bytes; + } + up_read(&mm->mmap_sem); + + return buf - old_buf; +} + +/* 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; + int buf_len = PAGE_SIZE; + int key_len = strlen(key); + unsigned long addr; + int rc; + bool skip = false; + ENTRY; + + buffer = kmalloc(buf_len, GFP_USER); + if (!buffer) + RETURN(-ENOMEM); + + mm = get_task_mm(current); + if (!mm) { + kfree(buffer); + RETURN(-EINVAL); + } + + addr = mm->env_start; + while (addr < mm->env_end) { + int this_len, retval, scan_len; + char *env_start, *env_end; + + memset(buffer, 0, buf_len); + + 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 < 0) + GOTO(out, rc = retval); + else if (retval != this_len) + break; + + addr += retval; + + /* Parse the buffer to find out the specified key/value pair. + * The "key=value" entries are separated by '\0'. */ + env_start = buffer; + scan_len = this_len; + while (scan_len) { + char *entry; + int entry_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)) { + /* 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 > 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) { + memcpy(value, entry, *val_len); + value[*val_len - 1] = 0; + GOTO(out, rc = -EOVERFLOW); + } + + 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); + 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: