netlib.narod.ru< Назад | Оглавление | Далее >

kernel/capability.c

22460 /*
22461  * linux/kernel/capability.c
22462  *
22463  * Copyright (C) 1997  Andrew Main <zefram@fysh.org>
22464  * Integrated into 2.1.97+, Andrew G. Morgan
22465  * <morgan@transmeta.com>
22466  */
22467 
22468 #include <linux/mm.h>
22469 #include <asm/uaccess.h>
22470 
22471 /* Note: never hold tasklist_lock while spinning for this
22472  * one */
22473 spinlock_t task_capability_lock;
22474 
22475 /* For sys_getproccap() and sys_setproccap(), any of the
22476  * three capability set pointers may be NULL --
22477  * indicating that that set is uninteresting and/or not
22478  * to be changed.  */
22479 
 Комментарий
22480 asmlinkage int sys_capget(cap_user_header_t header,
22481                           cap_user_data_t dataptr)
22482 {
22483      int error, pid;
22484      __u32 version;
22485      struct task_struct *target;
22486      struct __user_cap_data_struct data;
22487 
22488      if (get_user(version, &header->version))
22489        return -EFAULT;
22490 
22491      error = -EINVAL;
22492      if (version != _LINUX_CAPABILITY_VERSION) {
22493        version = _LINUX_CAPABILITY_VERSION;
22494        if (put_user(version, &header->version))
22495          error = -EFAULT;
22496        return error;
22497      }
22498 
22499      if (get_user(pid, &header->pid))
22500        return -EFAULT;
22501 
22502      if (pid < 0)
22503        return -EINVAL;
22504 
22505      error = 0;
22506 
22507      spin_lock(&task_capability_lock);
22508 
22509      if (pid && pid != current->pid) {
22510        read_lock(&tasklist_lock);
22511        /* identify target of query */
22512        target = find_task_by_pid(pid);
22513        if (!target)
22514          error = -ESRCH;
22515      } else {
22516        target = current;
22517      }
22518 
22519      if (!error) {
22520        data.permitted = cap_t(target->cap_permitted);
22521        data.inheritable = cap_t(target->cap_inheritable);
22522        data.effective = cap_t(target->cap_effective);
22523      }
22524 
22525      if (target != current)
22526        read_unlock(&tasklist_lock);
22527      spin_unlock(&task_capability_lock);
22528 
22529      if (!error) {
22530        if (copy_to_user(dataptr, &data, sizeof data))
22531          return -EFAULT;
22532      }
22533 
22534      return error;
22535 }
22536 
22537 /* set capabilities for all processes in a given process
22538  * group */
22539 static void cap_set_pg(int pgrp,
22540         kernel_cap_t *effective,
22541         kernel_cap_t *inheritable,
22542         kernel_cap_t *permitted)
22543 {
22544      struct task_struct *target;
22545 
22546      /* FIXME: do we need to have a write lock here..? */
22547      read_lock(&tasklist_lock);
22548      for_each_task(target) {
22549        if (target->pgrp != pgrp)
22550          continue;
22551        target->cap_effective   = *effective;
22552        target->cap_inheritable = *inheritable;
22553        target->cap_permitted   = *permitted;
22554      }
22555      read_unlock(&tasklist_lock);
22556 }
22557 
22558 /* set capabilities for all processes other than 1 and
22559  * self */
22560 
22561 static void cap_set_all(kernel_cap_t *effective,
22562          kernel_cap_t *inheritable,
22563          kernel_cap_t *permitted)
22564 {
22565      struct task_struct *target;
22566 
22567      /* FIXME: do we need to have a write lock here..? */
22568      read_lock(&tasklist_lock);
22569      /* ALL means everyone other than self or 'init' */
22570      for_each_task(target) {
22571        if (target == current || target->pid == 1)
22572          continue;
22573        target->cap_effective   = *effective;
22574        target->cap_inheritable = *inheritable;
22575        target->cap_permitted   = *permitted;
22576      }
22577      read_unlock(&tasklist_lock);
22578 }
22579 
22580 /* The restrictions on setting capabilities are specified
22581  * as:
22582  *
22583  * [pid is for the 'target' task.  'current' is the
22584  * calling task.]
22585  *
22586  * I: any raised capabilities must be a subset of the
22587  * (old current) Permitted
22588  * P: any raised capabilities must be a subset of the
22589  * (old current) permitted
22590  * E: must be set to a subset of (new target) Permitted
22591  */
 Комментарий
22592 asmlinkage int sys_capset(cap_user_header_t header,
22593                           const cap_user_data_t data)
22594 {
22595      kernel_cap_t inheritable, permitted, effective;
22596      __u32 version;
22597      struct task_struct *target;
22598      int error, pid;
22599 
22600      if (get_user(version, &header->version))
22601        return -EFAULT;
22602 
22603      if (version != _LINUX_CAPABILITY_VERSION) {
22604        version = _LINUX_CAPABILITY_VERSION;
22605        if (put_user(version, &header->version))
22606          return -EFAULT;
22607        return -EINVAL;
22608      }
22609 
22610      if (get_user(pid, &header->pid))
22611        return -EFAULT;
22612 
22613      if (pid && !capable(CAP_SETPCAP))
22614        return -EPERM;
22615 
22616      if (copy_from_user(&effective, &data->effective,
22617                         sizeof(effective)) ||
22618          copy_from_user(&inheritable, &data->inheritable,
22619                         sizeof(inheritable)) ||
22620          copy_from_user(&permitted, &data->permitted,
22621                         sizeof(permitted)))
22622        return -EFAULT;
22623 
22624      error = -EPERM;
22625      spin_lock(&task_capability_lock);
22626 
22627      if (pid > 0 && pid != current->pid) {
22628        read_lock(&tasklist_lock);
22629        /* identify target of query */
22630        target = find_task_by_pid(pid);
22631        if (!target) {
22632          error = -ESRCH;
22633          goto out;
22634        }
22635      } else {
22636        target = current;
22637      }
22638 
22639 
22640      /* verify restrictions on target's new Inheritable
22641       * set */
22642      if (!cap_issubset(inheritable,
22643            cap_combine(target->cap_inheritable,
22644            current->cap_permitted))) {
22645        goto out;
22646      }
22647 
22648      /* verify restrictions on target's new Permitted
22649       * set */
22650      if (!cap_issubset(permitted,
22651            cap_combine(target->cap_permitted,
22652            current->cap_permitted))) {
22653        goto out;
22654      }
22655 
22656      /* verify the _new_Effective_ is a subset of the
22657       * _new_Permitted_ */
22658      if (!cap_issubset(effective, permitted)) {
22659        goto out;
22660      }
22661 
22662      /* having verified that the proposed changes are
22663       * legal, we now put them into effect. */
22664      error = 0;
22665 
22666      if (pid < 0) {
22667        if (pid == -1) /* all procs but current & init */
22668          cap_set_all(&effective,&inheritable,&permitted);
22669 
22670        else            /* all procs in process group */
22671          cap_set_pg(-pid, &effective, &inheritable,
22672                     &permitted);
22673        goto spin_out;
22674      } else {
22675        /* FIXME: do we need a write lock here..?  */
22676        target->cap_effective   = effective;
22677        target->cap_inheritable = inheritable;
22678        target->cap_permitted   = permitted;
22679      }
22680 
22681 out:
22682      if (target != current) {
22683        read_unlock(&tasklist_lock);
22684      }
22685 spin_out:
22686      spin_unlock(&task_capability_lock);
22687      return error;
22688 }

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz