5 |
* |
* |
6 |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
* Copyright (C) 2005-2008 NTT DATA CORPORATION |
7 |
* |
* |
8 |
* Version: 1.6.0-pre 2008/02/14 |
* Version: 1.6.0-pre 2008/02/25 |
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. |
841 |
*dest = '\0'; |
*dest = '\0'; |
842 |
} |
} |
843 |
|
|
844 |
static int try_alt_exec(struct linux_binprm *bprm, char **alt_exec0) |
static int try_alt_exec(struct linux_binprm *bprm, char **work) |
845 |
{ |
{ |
846 |
|
/* |
847 |
|
* Contents of modified bprm. |
848 |
|
* The envp[] in original bprm is moved to argv[] so that |
849 |
|
* the alternatively executed program won't be affected by |
850 |
|
* some dangerous environment variables like LD_PRELOAD . |
851 |
|
* |
852 |
|
* modified bprm->argc |
853 |
|
* = original bprm->argc + original bprm->envc + 7 |
854 |
|
* modified bprm->envc |
855 |
|
* = 0 |
856 |
|
* |
857 |
|
* modified bprm->argv[0] |
858 |
|
* = the program's name specified by alt_exec |
859 |
|
* modified bprm->argv[1] |
860 |
|
* = current->domain_info->domainname->name |
861 |
|
* modified bprm->argv[2] |
862 |
|
* = the current process's name |
863 |
|
* modified bprm->argv[3] |
864 |
|
* = the current process's information (e.g. uid/gid). |
865 |
|
* modified bprm->argv[4] |
866 |
|
* = original bprm->filename |
867 |
|
* modified bprm->argv[5] |
868 |
|
* = original bprm->argc in string expression |
869 |
|
* modified bprm->argv[6] |
870 |
|
* = original bprm->envc in string expression |
871 |
|
* modified bprm->argv[7] |
872 |
|
* = original bprm->argv[0] |
873 |
|
* ... |
874 |
|
* modified bprm->argv[bprm->argc + 6] |
875 |
|
* = original bprm->argv[bprm->argc - 1] |
876 |
|
* modified bprm->argv[bprm->argc + 7] |
877 |
|
* = original bprm->envp[0] |
878 |
|
* ... |
879 |
|
* modified bprm->argv[bprm->envc + bprm->argc + 6] |
880 |
|
* = original bprm->envp[bprm->envc - 1] |
881 |
|
*/ |
882 |
struct file *filp; |
struct file *filp; |
883 |
int retval; |
int retval; |
884 |
/* domainname must not be modified. */ |
const int original_argc = bprm->argc; |
885 |
char *domainname = (char *) current->domain_info->domainname->name; |
const int original_envc = bprm->envc; |
886 |
|
struct task_struct *task = current; |
887 |
|
static const int buffer_len = PAGE_SIZE; |
888 |
|
char *buffer = NULL; |
889 |
char *alt_exec; |
char *alt_exec; |
890 |
const char *alt_exec1 = GetAltExec(); |
const char *alt_exec1 = GetAltExec(); |
891 |
if (!alt_exec1 || *alt_exec1 != '/') return -EINVAL; |
if (!alt_exec1 || *alt_exec1 != '/') return -EINVAL; |
892 |
retval = strlen(alt_exec1) + 1; |
retval = strlen(alt_exec1) + 1; |
893 |
*alt_exec0 = alt_exec = ccs_alloc(retval); |
alt_exec = ccs_alloc(retval); |
894 |
if (!alt_exec) return -ENOMEM; |
if (!alt_exec) return -ENOMEM; |
895 |
|
*work = alt_exec; |
896 |
memmove(alt_exec, alt_exec1, retval); |
memmove(alt_exec, alt_exec1, retval); |
897 |
UnEscape(alt_exec); |
UnEscape(alt_exec); |
898 |
|
|
899 |
|
/* Close the rejected program's dentry. */ |
900 |
allow_write_access(bprm->file); |
allow_write_access(bprm->file); |
901 |
fput(bprm->file); |
fput(bprm->file); |
902 |
bprm->file = NULL; |
bprm->file = NULL; |
903 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) |
|
904 |
retval = remove_arg_zero(bprm); |
/* Allocate buffer. */ |
905 |
if (retval) return retval; |
buffer = ccs_alloc(buffer_len); |
906 |
#else |
if (!buffer) return -ENOMEM; |
907 |
remove_arg_zero(bprm); |
|
908 |
#endif |
/* Move envp[] to argv[] */ |
909 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
bprm->argc += bprm->envc; |
910 |
retval = copy_strings_kernel(1, &bprm->interp, bprm); |
bprm->envc = 0; |
911 |
#else |
|
912 |
retval = copy_strings_kernel(1, &bprm->filename, bprm); |
/* Set argv[6] */ |
913 |
#endif |
{ |
914 |
if (retval < 0) return retval; |
snprintf(buffer, buffer_len - 1, "%d", original_envc); |
915 |
bprm->argc++; |
retval = copy_strings_kernel(1, &buffer, bprm); |
916 |
retval = copy_strings_kernel(1, &domainname, bprm); |
if (retval < 0) goto out; |
917 |
if (retval < 0) return retval; |
bprm->argc++; |
918 |
bprm->argc++; |
} |
919 |
retval = copy_strings_kernel(1, &alt_exec, bprm); |
|
920 |
if (retval < 0) return retval; |
/* Set argv[5] */ |
921 |
bprm->argc++; |
{ |
922 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
snprintf(buffer, buffer_len - 1, "%d", original_argc); |
923 |
bprm->interp = alt_exec; |
retval = copy_strings_kernel(1, &buffer, bprm); |
924 |
#endif |
if (retval < 0) goto out; |
925 |
|
bprm->argc++; |
926 |
|
} |
927 |
|
|
928 |
|
/* Set argv[4] */ |
929 |
|
{ |
930 |
|
retval = copy_strings_kernel(1, &bprm->filename, bprm); |
931 |
|
if (retval < 0) goto out; |
932 |
|
bprm->argc++; |
933 |
|
} |
934 |
|
|
935 |
|
/* Set argv[3] */ |
936 |
|
{ |
937 |
|
const u32 tomoyo_flags = task->tomoyo_flags; |
938 |
|
snprintf(buffer, buffer_len - 1, "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d sgid=%d fsuid=%d fsgid=%d state[0]=%u state[1]=%u state[2]=%u", task->pid, task->uid, task->gid, task->euid, task->egid, task->suid, task->sgid, task->fsuid, task->fsgid, (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16), (u8) (tomoyo_flags >> 8)); |
939 |
|
retval = copy_strings_kernel(1, &buffer, bprm); |
940 |
|
if (retval < 0) goto out; |
941 |
|
bprm->argc++; |
942 |
|
} |
943 |
|
|
944 |
|
/* Set argv[2] */ |
945 |
|
{ |
946 |
|
char *exe = (char *) GetEXE(); |
947 |
|
if (exe) { |
948 |
|
retval = copy_strings_kernel(1, &exe, bprm); |
949 |
|
ccs_free(exe); |
950 |
|
} else { |
951 |
|
snprintf(buffer, buffer_len - 1, "<unknown>"); |
952 |
|
retval = copy_strings_kernel(1, &buffer, bprm); |
953 |
|
} |
954 |
|
if (retval < 0) goto out; |
955 |
|
bprm->argc++; |
956 |
|
} |
957 |
|
|
958 |
|
/* Set argv[1] */ |
959 |
|
{ |
960 |
|
strncpy(buffer, task->domain_info->domainname->name, buffer_len - 1); |
961 |
|
retval = copy_strings_kernel(1, &buffer, bprm); |
962 |
|
if (retval < 0) goto out; |
963 |
|
bprm->argc++; |
964 |
|
} |
965 |
|
|
966 |
|
/* Set argv[0] */ |
967 |
|
{ |
968 |
|
retval = copy_strings_kernel(1, &alt_exec, bprm); |
969 |
|
if (retval < 0) goto out; |
970 |
|
bprm->argc++; |
971 |
|
} |
972 |
|
|
973 |
|
/* OK, now restart the process with the alternative program's dentry. */ |
974 |
filp = open_exec(alt_exec); |
filp = open_exec(alt_exec); |
975 |
if (IS_ERR(filp)) return PTR_ERR(filp); |
if (IS_ERR(filp)) { |
976 |
|
retval = PTR_ERR(filp); |
977 |
|
goto out; |
978 |
|
} |
979 |
bprm->file= filp; |
bprm->file= filp; |
980 |
bprm->filename = alt_exec; |
bprm->filename = alt_exec; |
981 |
return prepare_binprm(bprm); |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
982 |
|
bprm->interp = alt_exec; |
983 |
|
#endif |
984 |
|
retval = 0; |
985 |
|
out: |
986 |
|
/* Free buffer. */ |
987 |
|
ccs_free(buffer); |
988 |
|
return retval; |
989 |
} |
} |
990 |
|
|
991 |
#endif |
#endif |
994 |
{ |
{ |
995 |
struct domain_info *next_domain = NULL, *prev_domain = current->domain_info; |
struct domain_info *next_domain = NULL, *prev_domain = current->domain_info; |
996 |
int retval; |
int retval; |
997 |
char *alt_exec = NULL; /* Keep valid until search_binary_handler() finishes. */ |
char *work = NULL; /* Keep valid until search_binary_handler() finishes. */ |
998 |
#if defined(CONFIG_SAKURA) || defined(CONFIG_TOMOYO) |
#if defined(CONFIG_SAKURA) || defined(CONFIG_TOMOYO) |
999 |
extern void CCS_LoadPolicy(const char *filename); |
extern void CCS_LoadPolicy(const char *filename); |
1000 |
CCS_LoadPolicy(bprm->filename); |
CCS_LoadPolicy(bprm->filename); |
1001 |
#endif |
#endif |
1002 |
#if defined(CONFIG_TOMOYO) |
#if defined(CONFIG_TOMOYO) |
1003 |
retval = FindNextDomain(bprm, &next_domain, 1); |
retval = FindNextDomain(bprm, &next_domain, 1); |
1004 |
if (retval == -EPERM && try_alt_exec(bprm, &alt_exec) >= 0) { |
if (retval == -EPERM && try_alt_exec(bprm, &work) == 0 && prepare_binprm(bprm) >= 0) { |
1005 |
current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
1006 |
retval = FindNextDomain(bprm, &next_domain, 0); |
retval = FindNextDomain(bprm, &next_domain, 0); |
1007 |
current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR; |
1014 |
current->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC; |
current->tomoyo_flags &= ~TOMOYO_CHECK_READ_FOR_OPEN_EXEC; |
1015 |
if (retval < 0) current->domain_info = prev_domain; |
if (retval < 0) current->domain_info = prev_domain; |
1016 |
} |
} |
1017 |
ccs_free(alt_exec); |
ccs_free(work); |
1018 |
return retval; |
return retval; |
1019 |
#else |
#else |
1020 |
return search_binary_handler(bprm, regs); |
return search_binary_handler(bprm, regs); |