게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
??????
게시물ID : jisik_168221짧은주소 복사하기
작성자 : 퍼플캡
추천 : 0
조회수 : 433회
댓글수 : 2개
등록시간 : 2014/01/21 15:58:48
struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; 
struct group_info *groups_alloc(int gidsetsize){    struct group_info *group_info; 
    int nblocks;    int i; 
    nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK; 
    /* Make sure we always allocate at least one indirect block pointer */ 
    nblocks = nblocks ? : 1; 
    group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER); 
    if (!group_info)        return NULL;    group_info->ngroups = gidsetsize; 
    group_info->nblocks = nblocks;    atomic_set(&group_info->usage, 1); 
    if (gidsetsize <= NGROUPS_SMALL) 
        group_info->blocks[0] = group_info->small_block;    else { 
        for (i = 0; i < nblocks; i++) {            gid_t *b; 
            b = (void *)__get_free_page(GFP_USER);            if (!b) 
                goto out_undo_partial_alloc;            group_info->blocks[i] = b;        }    } 
    return group_info;out_undo_partial_alloc:    while (--i >= 0) { 
        free_page((unsigned long)group_info->blocks[i]);    }    kfree(group_info); 
    return NULL;}EXPORT_SYMBOL(groups_alloc); 
void groups_free(struct group_info *group_info){ 
    if (group_info->blocks[0] != group_info->small_block) {        int i; 
        for (i = 0; i < group_info->nblocks; i++) 
            free_page((unsigned long)group_info->blocks[i]);    }    kfree(group_info);} 
EXPORT_SYMBOL(groups_free);/* export the group_info to a user-space array */ 
static int groups_to_user(gid_t __user *grouplist, 
              const struct group_info *group_info){    int i; 
    unsigned int count = group_info->ngroups; 
    for (i = 0; i < group_info->nblocks; i++) { 
        unsigned int cp_count = min(NGROUPS_PER_BLOCK, count); 
        unsigned int len = cp_count * sizeof(*grouplist); 
        if (copy_to_user(grouplist, group_info->blocks[i], len))            return -EFAULT; 
        grouplist += NGROUPS_PER_BLOCK;        count -= cp_count;    }    return 0;} 
/* fill a group_info from a user-space array - it must be allocated already */ 
static int groups_from_user(struct group_info *group_info, 
    gid_t __user *grouplist){    int i; 
    unsigned int count = group_info->ngroups; 
    for (i = 0; i < group_info->nblocks; i++) { 
        unsigned int cp_count = min(NGROUPS_PER_BLOCK, count); 
        unsigned int len = cp_count * sizeof(*grouplist); 
        if (copy_from_user(group_info->blocks[i], grouplist, len)) 
            return -EFAULT;        grouplist += NGROUPS_PER_BLOCK;        count -= cp_count;    } 
    return 0;}/* a simple Shell sort */ 
static void groups_sort(struct group_info *group_info){    int base, max, stride; 
    int gidsetsize = group_info->ngroups; 
    for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1) 
        ; /* nothing */    stride /= 3;    while (stride) {        max = gidsetsize - stride; 
        for (base = 0; base < max; base++) {            int left = base; 
            int right = left + stride;            gid_t tmp = GROUP_AT(group_info, right); 
            while (left >= 0 && GROUP_AT(group_info, left) > tmp) { 
                GROUP_AT(group_info, right) =                    GROUP_AT(group_info, left); 
                right = left;                left -= stride;            }            GROUP_AT(group_info, right) = tmp;        } 
        stride /= 3;    }}/* a simple bsearch */ 
int groups_search(const struct group_info *group_info, gid_t grp){ 
    unsigned int left, right;    if (!group_info)        return 0;    left = 0; 
    right = group_info->ngroups;    while (left < right) { 
        unsigned int mid = (left+right)/2;        if (grp > GROUP_AT(group_info, mid)) 
            left = mid + 1;        else if (grp < GROUP_AT(group_info, mid))            right = mid; 
        else            return 1;    }    return 0;}/** 
 * set_groups - Change a group subion in a set of credentials 
 * @new: The newly prepared set of credentials to alter 
 * @group_info: The group list to install * 
 * Validate a group subion and, if valid, insert it into a set 
 * of credentials. */ 
int set_groups(struct cred *new, struct group_info *group_info){ 
    put_group_info(new->group_info);    groups_sort(group_info); 
    get_group_info(group_info);    new->group_info = group_info;    return 0;} 
EXPORT_SYMBOL(set_groups);/** 
 * set_current_groups - Change current's group subion 
 * @group_info: The group list to impose * 
 * Validate a group subion and, if valid, impose it upon current's task 
 * security record. */int set_current_groups(struct group_info *group_info){ 
    struct cred *new;    int ret;    new = prepare_creds();    if (!new)        return -ENOMEM; 
    ret = set_groups(new, group_info);    if (ret < 0) {        abort_creds(new); 
        return ret;    }    return commit_creds(new);}EXPORT_SYMBOL(set_current_groups); 
SYSCALL_DEFINE2(getgroups, int, gidsetsize, gid_t __user *, grouplist){ 
    const struct cred *cred = current_cred();    int i;    if (gidsetsize < 0) 
        return -EINVAL;    /* no need to grab task_lock here; it cannot change */ 
    i = cred->group_info->ngroups;    if (gidsetsize) { 
        if (i > gidsetsize) {            i = -EINVAL;            goto out;        } 
        if (groups_to_user(grouplist, cred->group_info)) {            i = -EFAULT; 
            goto out;        }    }out:    return i;}/* 
 *    SMP: Our groups are copy-on-write. We can set them safely 
 *    without another task interfering. */ 
SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist){ 
    struct group_info *group_info;    int retval;    if (!nsown_capable(CAP_SETGID)) 
        return -EPERM;    if ((unsigned)gidsetsize > NGROUPS_MAX)        return -EINVAL; 
    group_info = groups_alloc(gidsetsize);    if (!group_info)        return -ENOMEM; 
    retval = groups_from_user(group_info, grouplist);    if (retval) { 
        put_group_info(group_info);        return retval;    } 
    retval = set_current_groups(group_info);    put_group_info(group_info); 
    return retval;}/* 
 * Check whether we're fsgid/egid or in the supplemental group.. */ 
int in_group_p(gid_t grp){    const struct cred *cred = current_cred(); 
    int retval = 1;    if (grp != cred->fsgid) 
        retval = groups_search(cred->group_info, grp);    return retval;} 
EXPORT_SYMBOL(in_group_p);int in_egroup_p(gid_t grp){ 
    const struct cred *cred = current_cred();    int retval = 1; 
    if (grp != cred->egid)        retval = groups_search(cred->group_info, grp); 
    return retval;}
 
이거 어디다 쓰는거죠?
그냥 막 쳐져있는건가요
전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호