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

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

Legend:
Removed from v.1032  
changed lines
  Added in v.1052

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