オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Diff of /trunk/1.6.x/ccs-patch/fs/tomoyo_signal.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 912 by kumaneko, Mon Jan 21 11:59:49 2008 UTC revision 1260 by kumaneko, Thu Jun 5 07:18:45 2008 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2008  NTT DATA CORPORATION   * Copyright (C) 2005-2008  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.0-pre   2008/01/21   * Version: 1.6.1   2008/06/05
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
12   *   *
13   */   */
 /***** TOMOYO Linux start. *****/  
14    
15  #include <linux/ccs_common.h>  #include <linux/ccs_common.h>
16  #include <linux/tomoyo.h>  #include <linux/tomoyo.h>
17  #include <linux/realpath.h>  #include <linux/realpath.h>
18    #include <linux/version.h>
19    
20  /*************************  VARIABLES  *************************/  /* To support PID namespace. */
21    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
22    #define find_task_by_pid find_task_by_vpid
23    #endif
24    
25  /* The initial domain. */  /**
26  extern struct domain_info KERNEL_DOMAIN;   * audit_signal_log - Audit signal log.
27     *
28  extern struct mutex domain_acl_lock;   * @signal:      Signal number.
29     * @dest_domain: Destination domainname.
30  /*************************  AUDIT FUNCTIONS  *************************/   * @is_granted:  True if this is a granted log.
31     * @profile:     Profile number used.
32  static int AuditSignalLog(const int signal, const struct path_info *dest_domain, const bool is_granted, const u8 profile, const u8 mode)   * @mode:        Access control mode used.
33     *
34     * Returns 0 on success, negative value otherwise.
35     */
36    static int audit_signal_log(const int signal,
37                                const struct path_info *dest_domain,
38                                const bool is_granted, const u8 profile,
39                                const u8 mode)
40  {  {
41          char *buf;          char *buf;
42          int len;          int len;
43          if (CanSaveAuditLog(is_granted) < 0) return -ENOMEM;          int len2;
44          len = dest_domain->total_len;          if (ccs_can_save_audit_log(is_granted) < 0)
45          if ((buf = InitAuditLog(&len, profile, mode)) == NULL) return -ENOMEM;                  return -ENOMEM;
46          snprintf(buf + strlen(buf), len - strlen(buf) - 1, KEYWORD_ALLOW_SIGNAL "%d %s\n", signal, dest_domain->name);          len = dest_domain->total_len + 64;
47          return WriteAuditLog(buf, is_granted);          buf = ccs_init_audit_log(&len, profile, mode, NULL);
48            if (!buf)
49                    return -ENOMEM;
50            len2 = strlen(buf);
51            snprintf(buf + len2, len - len2 - 1, KEYWORD_ALLOW_SIGNAL "%d %s\n",
52                     signal, dest_domain->name);
53            return ccs_write_audit_log(buf, is_granted);
54  }  }
55    
56  /*************************  SIGNAL ACL HANDLER  *************************/  /**
57     * update_signal_acl - Update "struct signal_acl_record" list.
58  static int AddSignalEntry(const int sig, const char *dest_pattern, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)   *
59     * @sig:          Signal number.
60     * @dest_pattern: Destination domainname.
61     * @domain:       Pointer to "struct domain_info".
62     * @condition:    Pointer to "struct condition_list". May be NULL.
63     * @is_delete:    True if it is a delete request.
64     *
65     * Returns 0 on success, negative value otherwise.
66     */
67    static int update_signal_acl(const int sig, const char *dest_pattern,
68                                 struct domain_info *domain,
69                                 const struct condition_list *condition,
70                                 const bool is_delete)
71  {  {
72          struct acl_info *ptr;          struct acl_info *ptr;
73          struct signal_acl_record *acl;          struct signal_acl_record *acl;
74          const struct path_info *saved_dest_pattern;          const struct path_info *saved_dest_pattern;
75          const u16 hash = sig;          const u16 hash = sig;
76          int error = -ENOMEM;          int error = -ENOMEM;
77          if (!domain) return -EINVAL;          if (!domain)
78          if (!dest_pattern || !IsCorrectDomain(dest_pattern, __FUNCTION__)) return -EINVAL;                  return -EINVAL;
79          if ((saved_dest_pattern = SaveName(dest_pattern)) == NULL) return -ENOMEM;          if (!dest_pattern || !ccs_is_correct_domain(dest_pattern, __func__))
80                    return -EINVAL;
81            saved_dest_pattern = ccs_save_name(dest_pattern);
82            if (!saved_dest_pattern)
83                    return -ENOMEM;
84          mutex_lock(&domain_acl_lock);          mutex_lock(&domain_acl_lock);
85          if (!is_delete) {          if (is_delete)
86                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {                  goto delete;
87                          if ((ptr->type & ~(ACL_DELETED | ACL_WITH_CONDITION)) != TYPE_SIGNAL_ACL) continue;          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
88                          if (GetConditionPart(ptr) != condition) continue;                  if (ccs_acl_type1(ptr) != TYPE_SIGNAL_ACL)
89                          acl = container_of(ptr, struct signal_acl_record, head);                          continue;
90                          if (acl->sig != hash || pathcmp(acl->domainname, saved_dest_pattern)) continue;                  if (ccs_get_condition_part(ptr) != condition)
91                          error = AddDomainACL(NULL, ptr);                          continue;
92                          goto out;                  acl = container_of(ptr, struct signal_acl_record, head);
93                  }                  if (acl->sig != hash ||
94                  /* Not found. Append it to the tail. */                      ccs_pathcmp(acl->domainname, saved_dest_pattern))
95                  if ((acl = alloc_acl_element(TYPE_SIGNAL_ACL, condition)) == NULL) goto out;                          continue;
96                  acl->sig = hash;                  error = ccs_add_domain_acl(NULL, ptr);
97                  acl->domainname = saved_dest_pattern;                  goto out;
98                  error = AddDomainACL(domain, &acl->head);          }
99          } else {          /* Not found. Append it to the tail. */
100                  error = -ENOENT;          acl = ccs_alloc_acl_element(TYPE_SIGNAL_ACL, condition);
101                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {          if (!acl)
102                          if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_SIGNAL_ACL) continue;                  goto out;
103                          if (GetConditionPart(ptr) != condition) continue;          acl->sig = hash;
104                          acl = container_of(ptr, struct signal_acl_record, head);          acl->domainname = saved_dest_pattern;
105                          if (acl->sig != hash || pathcmp(acl->domainname, saved_dest_pattern)) continue;          error = ccs_add_domain_acl(domain, &acl->head);
106                          error = DelDomainACL(ptr);          goto out;
107                          break;   delete:
108                  }          error = -ENOENT;
109            list1_for_each_entry(ptr, &domain->acl_info_list, list) {
110                    if (ccs_acl_type2(ptr) != TYPE_SIGNAL_ACL)
111                            continue;
112                    if (ccs_get_condition_part(ptr) != condition)
113                            continue;
114                    acl = container_of(ptr, struct signal_acl_record, head);
115                    if (acl->sig != hash ||
116                        ccs_pathcmp(acl->domainname, saved_dest_pattern))
117                            continue;
118                    error = ccs_del_domain_acl(ptr);
119                    break;
120          }          }
121   out: ;   out:
122          mutex_unlock(&domain_acl_lock);          mutex_unlock(&domain_acl_lock);
123          return error;          return error;
124  }  }
125    
126  int CheckSignalACL(const int sig, const int pid)  /**
127     * ccs_check_signal_acl - Check permission for signal.
128     *
129     * @sig: Signal number.
130     * @pid: Target's PID.
131     *
132     * Returns 0 on success, negative value otherwise.
133     */
134    int ccs_check_signal_acl(const int sig, const int pid)
135  {  {
136          struct domain_info *domain = current->domain_info;          struct domain_info *domain = current->domain_info;
137          struct domain_info *dest = NULL;          struct domain_info *dest = NULL;
# Line 88  int CheckSignalACL(const int sig, const Line 139  int CheckSignalACL(const int sig, const
139          struct acl_info *ptr;          struct acl_info *ptr;
140          const u16 hash = sig;          const u16 hash = sig;
141          const u8 profile = current->domain_info->profile;          const u8 profile = current->domain_info->profile;
142          const u8 mode = CheckCCSFlags(CCS_TOMOYO_MAC_FOR_SIGNAL);          const u8 mode = ccs_check_flags(CCS_TOMOYO_MAC_FOR_SIGNAL);
143          const bool is_enforce = (mode == 3);          const bool is_enforce = (mode == 3);
144          bool found = 0;          bool found = false;
145          if (!mode) return 0;          if (!mode)
146          if (!sig) return 0;                               /* No check for NULL signal. */                  return 0;
147            if (!sig)
148                    return 0;                /* No check for NULL signal. */
149          if (current->pid == pid) {          if (current->pid == pid) {
150                  AuditSignalLog(sig, domain->domainname, 1, profile, mode);                  audit_signal_log(sig, domain->domainname, true, profile, mode);
151                  return 0;                /* No check for self. */                  return 0;                /* No check for self process. */
152          }          }
153          { /* Simplified checking. */          { /* Simplified checking. */
154                  struct task_struct *p = NULL;                  struct task_struct *p = NULL;
155                    /***** CRITICAL SECTION START *****/
156                  read_lock(&tasklist_lock);                  read_lock(&tasklist_lock);
157                  if (pid > 0) p = find_task_by_pid((pid_t) pid);                  if (pid > 0)
158                  else if (pid == 0) p = current;                          p = find_task_by_pid((pid_t) pid);
159                  else if (pid == -1) dest = &KERNEL_DOMAIN;                  else if (pid == 0)
160                  else p = find_task_by_pid((pid_t) -pid);                          p = current;
161                  if (p) dest = p->domain_info;                  else if (pid == -1)
162                            dest = &KERNEL_DOMAIN;
163                    else
164                            p = find_task_by_pid((pid_t) -pid);
165                    if (p)
166                            dest = p->domain_info;
167                  read_unlock(&tasklist_lock);                  read_unlock(&tasklist_lock);
168                  if (!dest) return 0; /* I can't find destinatioin. */                  /***** CRITICAL SECTION END *****/
169                    if (!dest)
170                            return 0; /* I can't find destinatioin. */
171          }          }
172          if (domain == dest) {          if (domain == dest) {
173                  AuditSignalLog(sig, dest->domainname, 1, profile, mode);                  audit_signal_log(sig, dest->domainname, true, profile, mode);
174                  return 0;                  return 0;                /* No check for self domain. */
175          }          }
176          dest_pattern = dest->domainname->name;          dest_pattern = dest->domainname->name;
177          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
178                  struct signal_acl_record *acl;                  struct signal_acl_record *acl;
179                  if ((ptr->type & ~ACL_WITH_CONDITION) != TYPE_SIGNAL_ACL) continue;                  if (ccs_acl_type2(ptr) != TYPE_SIGNAL_ACL)
180                            continue;
181                  acl = container_of(ptr, struct signal_acl_record, head);                  acl = container_of(ptr, struct signal_acl_record, head);
182                  if (acl->sig == hash && CheckCondition(ptr, NULL)) {                  if (acl->sig == hash && ccs_check_condition(ptr, NULL)) {
183                          const int len = acl->domainname->total_len;                          const int len = acl->domainname->total_len;
184                          if (strncmp(acl->domainname->name, dest_pattern, len)) continue;                          if (strncmp(acl->domainname->name, dest_pattern, len))
185                          if (dest_pattern[len] != ' ' && dest_pattern[len] != '\0') continue;                                  continue;
186                          found = 1;                          switch (dest_pattern[len]) {
187                            case ' ':
188                            case '\0':
189                                    break;
190                            default:
191                                    continue;
192                            }
193                            ccs_update_condition(ptr);
194                            found = true;
195                          break;                          break;
196                  }                  }
197          }          }
198          AuditSignalLog(sig, dest->domainname, found, profile, mode);          audit_signal_log(sig, dest->domainname, found, profile, mode);
199          if (found) return 0;          if (found)
200          if (TomoyoVerboseMode()) {                  return 0;
201                  printk("TOMOYO-%s: Signal %d to %s denied for %s\n", GetMSG(is_enforce), sig, GetLastName(dest), GetLastName(domain));          if (ccs_verbose_mode())
202          }                  printk(KERN_WARNING "TOMOYO-%s: Signal %d "
203          if (is_enforce) return CheckSupervisor("%s\n" KEYWORD_ALLOW_SIGNAL "%d %s\n", domain->domainname->name, sig, dest_pattern);                         "to %s denied for %s\n", ccs_get_msg(is_enforce), sig,
204          else if (mode == 1 && CheckDomainQuota(domain)) AddSignalEntry(sig, dest_pattern, domain, NULL, 0);                         ccs_get_last_name(dest), ccs_get_last_name(domain));
205            if (is_enforce)
206                    return ccs_check_supervisor(NULL, KEYWORD_ALLOW_SIGNAL
207                                                "%d %s\n", sig, dest_pattern);
208            if (mode == 1 && ccs_check_domain_quota(domain))
209                    update_signal_acl(sig, dest_pattern, domain, NULL, false);
210          return 0;          return 0;
211  }  }
212    
213  int AddSignalPolicy(char *data, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)  /**
214     * ccs_write_signal_policy - Write "struct signal_acl_record" list.
215     *
216     * @data:      String to parse.
217     * @domain:    Pointer to "struct domain_info".
218     * @condition: Pointer to "struct condition_list". May be NULL.
219     * @is_delete: True if it is a delete request.
220     *
221     * Returns 0 on success, negative value otherwise.
222     */
223    int ccs_write_signal_policy(char *data, struct domain_info *domain,
224                                const struct condition_list *condition,
225                                const bool is_delete)
226  {  {
227          int sig;          int sig;
228          char *domainname = strchr(data, ' ');          char *domainname = strchr(data, ' ');
229          if (sscanf(data, "%d", &sig) == 1 && domainname && IsDomainDef(domainname + 1)) {          if (sscanf(data, "%d", &sig) == 1 && domainname &&
230                  return AddSignalEntry(sig, domainname + 1, domain, condition, is_delete);              ccs_is_domain_def(domainname + 1))
231          }                  return update_signal_acl(sig, domainname + 1, domain,
232                                             condition, is_delete);
233          return -EINVAL;          return -EINVAL;
234  }  }
   
 /***** TOMOYO Linux end. *****/  

Legend:
Removed from v.912  
changed lines
  Added in v.1260

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26