3 |
* |
* |
4 |
* Get the canonicalized absolute pathnames. The basis for SAKURA and TOMOYO. |
* Get the canonicalized absolute pathnames. The basis for SAKURA and TOMOYO. |
5 |
* |
* |
6 |
* Copyright (C) 2005-2007 NTT DATA CORPORATION |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.5.2-pre 2007/10/19 |
* Version: 1.6.0-pre 2008/02/16 |
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. |
193 |
{ |
{ |
194 |
struct nameidata nd; |
struct nameidata nd; |
195 |
if (pathname && path_lookup(pathname, lookup_flags, &nd) == 0) { |
if (pathname && path_lookup(pathname, lookup_flags, &nd) == 0) { |
196 |
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,25) |
197 |
|
char *buf = realpath_from_dentry(nd.path.dentry, nd.path.mnt); |
198 |
|
path_put(&nd.path); |
199 |
|
#else |
200 |
char *buf = realpath_from_dentry(nd.dentry, nd.mnt); |
char *buf = realpath_from_dentry(nd.dentry, nd.mnt); |
201 |
path_release(&nd); |
path_release(&nd); |
202 |
|
#endif |
203 |
return buf; |
return buf; |
204 |
} |
} |
205 |
return NULL; |
return NULL; |
209 |
{ |
{ |
210 |
struct nameidata nd; |
struct nameidata nd; |
211 |
if (pathname && path_lookup(pathname, lookup_flags ^ LOOKUP_FOLLOW, &nd) == 0) { |
if (pathname && path_lookup(pathname, lookup_flags ^ LOOKUP_FOLLOW, &nd) == 0) { |
212 |
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,25) |
213 |
|
char *buf = realpath_from_dentry(nd.path.dentry, nd.path.mnt); |
214 |
|
path_put(&nd.path); |
215 |
|
#else |
216 |
char *buf = realpath_from_dentry(nd.dentry, nd.mnt); |
char *buf = realpath_from_dentry(nd.dentry, nd.mnt); |
217 |
path_release(&nd); |
path_release(&nd); |
218 |
|
#endif |
219 |
return buf; |
return buf; |
220 |
} |
} |
221 |
return NULL; |
return NULL; |
290 |
#define MAX_HASH 256 |
#define MAX_HASH 256 |
291 |
|
|
292 |
struct name_entry { |
struct name_entry { |
293 |
struct name_entry *next; /* Pointer to next record. NULL if none. */ |
struct list1_head list; |
294 |
struct path_info entry; |
struct path_info entry; |
295 |
}; |
}; |
296 |
|
|
297 |
struct free_memory_block_list { |
struct free_memory_block_list { |
298 |
struct free_memory_block_list *next; /* Pointer to next record. NULL if none. */ |
struct list_head list; |
299 |
char *ptr; /* Pointer to a free area. */ |
char *ptr; /* Pointer to a free area. */ |
300 |
int len; /* Length of the area. */ |
int len; /* Length of the area. */ |
301 |
}; |
}; |
302 |
|
|
303 |
|
static struct list1_head name_list[MAX_HASH]; /* The list of names. */ |
304 |
|
|
305 |
/* Keep the given name on the RAM. The RAM is shared, so NEVER try to modify or kfree() the returned name. */ |
/* Keep the given name on the RAM. The RAM is shared, so NEVER try to modify or kfree() the returned name. */ |
306 |
const struct path_info *SaveName(const char *name) |
const struct path_info *SaveName(const char *name) |
307 |
{ |
{ |
308 |
static struct free_memory_block_list fmb_list = { NULL, NULL, 0 }; |
static LIST_HEAD(fmb_list); |
|
static struct name_entry name_list[MAX_HASH]; /* The list of names. */ |
|
309 |
static DEFINE_MUTEX(lock); |
static DEFINE_MUTEX(lock); |
310 |
struct name_entry *ptr, *prev = NULL; |
struct name_entry *ptr; |
311 |
unsigned int hash; |
unsigned int hash; |
312 |
struct free_memory_block_list *fmb = &fmb_list; |
struct free_memory_block_list *fmb; |
313 |
int len; |
int len; |
314 |
static int first_call = 1; |
char *cp; |
315 |
if (!name) return NULL; |
if (!name) return NULL; |
316 |
len = strlen(name) + 1; |
len = strlen(name) + 1; |
317 |
if (len > CCS_MAX_PATHNAME_LEN) { |
if (len > CCS_MAX_PATHNAME_LEN) { |
320 |
} |
} |
321 |
hash = full_name_hash((const unsigned char *) name, len - 1); |
hash = full_name_hash((const unsigned char *) name, len - 1); |
322 |
mutex_lock(&lock); |
mutex_lock(&lock); |
323 |
if (first_call) { |
list1_for_each_entry(ptr, &name_list[hash % MAX_HASH], list) { |
|
int i; |
|
|
first_call = 0; |
|
|
memset(&name_list, 0, sizeof(name_list)); |
|
|
for (i = 0; i < MAX_HASH; i++) { |
|
|
name_list[i].entry.name = "/"; |
|
|
fill_path_info(&name_list[i].entry); |
|
|
} |
|
|
if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE) panic("Bad size."); |
|
|
} |
|
|
ptr = &name_list[hash % MAX_HASH]; |
|
|
while (ptr) { |
|
324 |
if (hash == ptr->entry.hash && strcmp(name, ptr->entry.name) == 0) goto out; |
if (hash == ptr->entry.hash && strcmp(name, ptr->entry.name) == 0) goto out; |
|
prev = ptr; ptr = ptr->next; |
|
325 |
} |
} |
326 |
while (len > fmb->len) { |
list_for_each_entry(fmb, &fmb_list, list) { |
327 |
if (fmb->next) { |
if (len <= fmb->len) goto ready; |
|
fmb = fmb->next; |
|
|
} else { |
|
|
char *cp; |
|
|
if ((cp = kmalloc(PAGE_SIZE, GFP_KERNEL)) == NULL || (fmb->next = alloc_element(sizeof(*fmb))) == NULL) { |
|
|
kfree(cp); |
|
|
printk("ERROR: Out of memory for SaveName().\n"); |
|
|
if (!sbin_init_started) panic("MAC Initialization failed.\n"); |
|
|
goto out; /* ptr == NULL */ |
|
|
} |
|
|
memset(cp, 0, PAGE_SIZE); |
|
|
allocated_memory_for_savename += PAGE_SIZE; |
|
|
fmb = fmb->next; |
|
|
fmb->ptr = cp; |
|
|
fmb->len = PAGE_SIZE; |
|
|
} |
|
328 |
} |
} |
329 |
if ((ptr = alloc_element(sizeof(*ptr))) == NULL) goto out; |
cp = kmalloc(PAGE_SIZE, GFP_KERNEL); |
330 |
|
fmb = kmalloc(sizeof(*fmb), GFP_KERNEL); |
331 |
|
if (!cp || !fmb) { |
332 |
|
kfree(cp); |
333 |
|
kfree(fmb); |
334 |
|
printk("ERROR: Out of memory for SaveName().\n"); |
335 |
|
if (!sbin_init_started) panic("MAC Initialization failed.\n"); |
336 |
|
ptr = NULL; |
337 |
|
goto out; |
338 |
|
} |
339 |
|
memset(cp, 0, PAGE_SIZE); |
340 |
|
allocated_memory_for_savename += PAGE_SIZE; |
341 |
|
list_add(&fmb->list, &fmb_list); |
342 |
|
fmb->ptr = cp; |
343 |
|
fmb->len = PAGE_SIZE; |
344 |
|
ready: |
345 |
|
ptr = alloc_element(sizeof(*ptr)); |
346 |
|
if (!ptr) goto out; |
347 |
ptr->entry.name = fmb->ptr; |
ptr->entry.name = fmb->ptr; |
348 |
memmove(fmb->ptr, name, len); |
memmove(fmb->ptr, name, len); |
349 |
fill_path_info(&ptr->entry); |
fill_path_info(&ptr->entry); |
350 |
fmb->ptr += len; |
fmb->ptr += len; |
351 |
fmb->len -= len; |
fmb->len -= len; |
352 |
prev->next = ptr; /* prev != NULL because name_list is not empty. */ |
list1_add_tail_mb(&ptr->list, &name_list[hash % MAX_HASH]); |
353 |
if (fmb->len == 0) { |
if (fmb->len == 0) { |
354 |
struct free_memory_block_list *ptr = &fmb_list; |
list_del(&fmb->list); |
355 |
while (ptr->next != fmb) ptr = ptr->next; ptr->next = fmb->next; |
kfree(fmb); |
356 |
} |
} |
357 |
out: |
out: |
358 |
mutex_unlock(&lock); |
mutex_unlock(&lock); |
375 |
|
|
376 |
void __init realpath_Init(void) |
void __init realpath_Init(void) |
377 |
{ |
{ |
378 |
|
int i; |
379 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) |
380 |
ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry), 0, 0, NULL); |
ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry), 0, 0, NULL); |
381 |
#else |
#else |
382 |
ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry), 0, 0, NULL, NULL); |
ccs_cachep = kmem_cache_create("ccs_cache", sizeof(struct cache_entry), 0, 0, NULL, NULL); |
383 |
#endif |
#endif |
384 |
if (!ccs_cachep) panic("Can't create cache.\n"); |
if (!ccs_cachep) panic("Can't create cache.\n"); |
385 |
|
for (i = 0; i < MAX_HASH; i++) { |
386 |
|
INIT_LIST1_HEAD(&name_list[i]); |
387 |
|
} |
388 |
|
if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE) panic("Bad size."); |
389 |
|
INIT_LIST1_HEAD(&KERNEL_DOMAIN.acl_info_list); |
390 |
|
KERNEL_DOMAIN.domainname = SaveName(ROOT_NAME); |
391 |
|
list1_add_tail_mb(&KERNEL_DOMAIN.list, &domain_list); |
392 |
|
if (FindDomain(ROOT_NAME) != &KERNEL_DOMAIN) panic("Can't register KERNEL_DOMAIN"); |
393 |
} |
} |
394 |
|
|
395 |
static LIST_HEAD(cache_list); |
static LIST_HEAD(cache_list); |