summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-05-07 02:55:41 +0000
commitdcec8a13bf565e47942a1751a9cec21bec5648fe (patch)
tree548b69625b18cc2e88c3e68d0923be546c9ebb03 /kernel
parent2e0f55e79c49509b7ff70ff1a10e1e9e90a3dfd4 (diff)
o Merge with Linux 2.1.99.
o Fix ancient bug in the ELF loader making ldd crash. o Fix ancient bug in the keyboard code for SGI, SNI and Jazz.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c21
-rw-r--r--kernel/fork.c9
-rw-r--r--kernel/kmod.c178
-rw-r--r--kernel/ksyms.c21
-rw-r--r--kernel/printk.c23
-rw-r--r--kernel/sched.c2
-rw-r--r--kernel/signal.c1
-rw-r--r--kernel/sys.c3
-rw-r--r--kernel/sysctl.c43
9 files changed, 118 insertions, 183 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 2d5835ac8..ae2a34f44 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -299,7 +299,10 @@ static void exit_notify(void)
* as a result of our exiting, and if they have any stopped
* jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
- while ((p = current->p_cptr) != NULL) {
+
+ write_lock_irq(&tasklist_lock);
+ while (current->p_cptr != NULL) {
+ p = current->p_cptr;
current->p_cptr = p->p_osptr;
p->p_ysptr = NULL;
p->flags &= ~(PF_PTRACED|PF_TRACESYS);
@@ -318,13 +321,19 @@ static void exit_notify(void)
* outside, so the child pgrp is now orphaned.
*/
if ((p->pgrp != current->pgrp) &&
- (p->session == current->session) &&
- is_orphaned_pgrp(p->pgrp) &&
- has_stopped_jobs(p->pgrp)) {
- kill_pg(p->pgrp,SIGHUP,1);
- kill_pg(p->pgrp,SIGCONT,1);
+ (p->session == current->session)) {
+ int pgrp = p->pgrp;
+
+ write_unlock_irq(&tasklist_lock);
+ if (is_orphaned_pgrp(pgrp) && has_stopped_jobs(pgrp)) {
+ kill_pg(pgrp,SIGHUP,1);
+ kill_pg(pgrp,SIGCONT,1);
+ }
+ write_lock_irq(&tasklist_lock);
}
}
+ write_unlock_irq(&tasklist_lock);
+
if (current->leader)
disassociate_ctty(1);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index a08aa2c64..88199cae1 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -208,6 +208,7 @@ static inline int dup_mmap(struct mm_struct * mm)
int retval;
flush_cache_mm(current->mm);
+ down(&current->mm->mmap_sem);
pprev = &mm->mmap;
for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
struct file *file;
@@ -257,6 +258,7 @@ static inline int dup_mmap(struct mm_struct * mm)
fail_nomem:
flush_tlb_mm(current->mm);
+ up(&current->mm->mmap_sem);
return retval;
}
@@ -298,13 +300,14 @@ struct mm_struct * mm_alloc(void)
void mmput(struct mm_struct *mm)
{
if (!--mm->count) {
+ release_segments(mm);
exit_mmap(mm);
free_page_tables(mm);
kmem_cache_free(mm_cachep, mm);
}
}
-static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
+static inline int copy_mm(int nr, unsigned long clone_flags, struct task_struct * tsk)
{
struct mm_struct * mm;
int retval;
@@ -324,6 +327,7 @@ static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
tsk->min_flt = tsk->maj_flt = 0;
tsk->cmin_flt = tsk->cmaj_flt = 0;
tsk->nswap = tsk->cnswap = 0;
+ copy_segments(nr, tsk, mm);
retval = new_page_tables(tsk);
if (retval)
goto free_mm;
@@ -514,6 +518,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
/* ?? should we just memset this ?? */
for(i = 0; i < smp_num_cpus; i++)
p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
+ spin_lock_init(&p->sigmask_lock);
}
#endif
p->lock_depth = 0;
@@ -539,7 +544,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
goto bad_fork_cleanup_files;
if (copy_sighand(clone_flags, p))
goto bad_fork_cleanup_fs;
- if (copy_mm(clone_flags, p))
+ if (copy_mm(nr, clone_flags, p))
goto bad_fork_cleanup_sighand;
error = copy_thread(nr, clone_flags, usp, p, regs);
if (error)
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 379c27695..7468e4382 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -1,6 +1,12 @@
/*
kmod, the new module loader (replaces kerneld)
Kirk Petersen
+
+ Reorganized not to be a daemon by Adam Richter, with guidance
+ from Greg Zornetzer.
+
+ Modified to avoid chroot and file sharing problems.
+ Mikael Pettersson
*/
#define __KERNEL_SYSCALLS__
@@ -8,140 +14,88 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/unistd.h>
+#include <asm/smp_lock.h>
+#include <asm/uaccess.h>
/*
- kmod_unload_delay and modprobe_path are set via /proc/sys.
+ modprobe_path is set via /proc/sys.
*/
-int kmod_unload_delay = 60;
char modprobe_path[256] = "/sbin/modprobe";
-static char module_name[64] = "";
-static char * argv[] = { "modprobe", "-k", module_name, NULL, };
-static char * envp[] = { "HOME=/", "TERM=linux", NULL, };
-
-/*
- kmod_queue synchronizes the kmod thread and the rest of the system
- kmod_unload_timer is what we use to unload modules
- after kmod_unload_delay seconds
-*/
-static struct wait_queue * kmod_queue = NULL;
-static struct timer_list kmod_unload_timer;
+static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };
/*
- kmod_thread is the thread that does most of the work. kmod_unload and
- request_module tell it to wake up and do work.
+ exec_modprobe is spawned from a kernel-mode user process,
+ then changes its state to behave _as_if_ it was spawned
+ from the kernel's init process
+ (ppid and {e,}gid are not adjusted, but that shouldn't
+ be a problem since we trust modprobe)
*/
-int kmod_thread(void * data)
-{
- int pid;
+#define task_init task[smp_num_cpus]
- /*
- Initialize basic thread information
- */
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "kmod");
- sigfillset(&current->blocked);
-
- /*
- This is the main kmod_thread loop. It first sleeps, then
- handles requests from request_module or kmod_unload.
- */
+static inline void
+use_init_file_context(void) {
+ lock_kernel();
- while (1) {
- interruptible_sleep_on(&kmod_queue);
-
- /*
- If request_module woke us up, we should try to
- load module_name. If not, kmod_unload woke us up,
- do call delete_module.
- (if somehow both want us to do something, ignore the
- delete_module request)
- */
- if (module_name[0] == '\0') {
- delete_module(NULL);
- } else {
- pid = fork();
- if (pid > 0) {
- waitpid(pid, NULL, 0);
- module_name[0] = '\0';
- wake_up(&kmod_queue);
- } else
- if (pid == 0) {
-
- /*
- Call modprobe with module_name. If execve returns,
- print out an error.
- */
- execve(modprobe_path, argv, envp);
-
- printk("kmod: failed to load module %s\n", module_name);
- _exit(0);
- } else {
- printk("error, fork failed in kmod\n");
- }
- }
- }
+ /* don't use the user's root, use init's root instead */
+ exit_fs(current); /* current->fs->count--; */
+ current->fs = task_init->fs;
+ current->fs->count++;
- return 0; /* Never reached. */
+ unlock_kernel();
}
-/*
- kmod_unload is the function that the kernel calls when
- the kmod_unload_timer expires
-*/
-void kmod_unload(unsigned long x)
+static int exec_modprobe(void * module_name)
{
- /*
- wake up the kmod thread, which does the work
- (we can't call delete_module, as it locks the kernel and
- we are in the bottom half of the kernel (right?))
- once it is awake, reset the timer
- */
- wake_up(&kmod_queue);
- kmod_unload_timer.expires = jiffies + (kmod_unload_delay * HZ);
- add_timer(&kmod_unload_timer);
-}
+ char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL};
+ int i;
-int kmod_init(void)
-{
- printk ("Starting kmod\n");
+ use_init_file_context();
- kernel_thread(kmod_thread, NULL, 0);
+ /* Prevent parent user process from sending signals to child.
+ Otherwise, if the modprobe program does not exist, it might
+ be possible to get a user defined signal handler to execute
+ as the super user right after the execve fails if you time
+ the signal just right.
+ */
+ spin_lock_irq(&current->sigmask_lock);
+ flush_signals(current);
+ flush_signal_handlers(current);
+ spin_unlock_irq(&current->sigmask_lock);
- kmod_unload_timer.next = NULL;
- kmod_unload_timer.prev = NULL;
- kmod_unload_timer.expires = jiffies + (5 * 60 * HZ);
- kmod_unload_timer.data = 0L;
- kmod_unload_timer.function = kmod_unload;
- add_timer(&kmod_unload_timer);
+ for (i = 0; i < current->files->max_fds; i++ ) {
+ if (current->files->fd[i]) close(i);
+ }
+ set_fs(KERNEL_DS); /* Allow execve args to be in kernel space. */
+ current->uid = current->euid = current->fsuid = 0;
+ if (execve(modprobe_path, argv, envp) < 0) {
+ printk(KERN_ERR
+ "kmod: failed to exec %s -s -k %s, errno = %d\n",
+ modprobe_path, (char*) module_name, errno);
+ return -errno;
+ }
return 0;
}
/*
- request_module, the function that everyone calls when they need a
- module to be loaded
+ request_module: the function that everyone calls when they need
+ a module.
*/
-int request_module(const char * name)
+int request_module(const char * module_name)
{
- /* first, copy the name of the module into module_name */
- /* then wake_up() the kmod daemon */
- /* wait for the kmod daemon to finish (it will wake us up) */
-
- /*
- kmod_thread is sleeping, so start by copying the name of
- the module into module_name. Once that is done, wake up
- kmod_thread.
- */
- strncpy(module_name, name, sizeof(module_name));
- module_name[sizeof(module_name)-1] = '\0';
- wake_up(&kmod_queue);
-
- /*
- Now that we have told kmod_thread what to do, we want to
- go to sleep and let it do its work. It will wake us up,
- at which point we will be done (the module will be loaded).
- */
- interruptible_sleep_on(&kmod_queue);
+ int pid;
+ int waitpid_result;
+
+ pid = kernel_thread(exec_modprobe, (void*) module_name,
+ CLONE_FS | SIGCHLD);
+ if (pid < 0) {
+ printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid);
+ return pid;
+ }
+ waitpid_result = waitpid(pid, NULL, 0);
+ if (waitpid_result != pid) {
+ printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
+ pid, waitpid_result);
+ }
return 0;
}
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 7ff40d7bd..61201da16 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -54,10 +54,6 @@
extern unsigned char aux_device_present, kbd_read_mask;
-#ifdef CONFIG_PCI
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#endif
#if defined(CONFIG_PROC_FS)
#include <linux/proc_fs.h>
#endif
@@ -100,19 +96,6 @@ EXPORT_SYMBOL(get_module_symbol);
#endif
EXPORT_SYMBOL(get_options);
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pcibios_present);
-EXPORT_SYMBOL(pcibios_find_class);
-EXPORT_SYMBOL(pcibios_find_device);
-EXPORT_SYMBOL(pcibios_read_config_byte);
-EXPORT_SYMBOL(pcibios_read_config_word);
-EXPORT_SYMBOL(pcibios_read_config_dword);
-EXPORT_SYMBOL(pcibios_write_config_byte);
-EXPORT_SYMBOL(pcibios_write_config_word);
-EXPORT_SYMBOL(pcibios_write_config_dword);
-EXPORT_SYMBOL(pcibios_strerror);
-#endif
-
/* process memory management */
EXPORT_SYMBOL(do_mmap);
EXPORT_SYMBOL(do_munmap);
@@ -265,6 +248,7 @@ EXPORT_SYMBOL(register_binfmt);
EXPORT_SYMBOL(unregister_binfmt);
EXPORT_SYMBOL(search_binary_handler);
EXPORT_SYMBOL(prepare_binprm);
+EXPORT_SYMBOL(compute_creds);
EXPORT_SYMBOL(remove_arg_zero);
/* execution environment registration */
@@ -295,6 +279,7 @@ EXPORT_SYMBOL(bh_mask_count);
EXPORT_SYMBOL(bh_base);
EXPORT_SYMBOL(add_timer);
EXPORT_SYMBOL(del_timer);
+EXPORT_SYMBOL(mod_timer);
EXPORT_SYMBOL(tq_timer);
EXPORT_SYMBOL(tq_immediate);
EXPORT_SYMBOL(tq_scheduler);
@@ -353,6 +338,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier);
EXPORT_SYMBOL(_ctype);
EXPORT_SYMBOL(secure_tcp_sequence_number);
EXPORT_SYMBOL(get_random_bytes);
+EXPORT_SYMBOL(securebits);
/* Program loader interfaces */
EXPORT_SYMBOL(setup_arg_pages);
@@ -388,7 +374,6 @@ EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(event);
EXPORT_SYMBOL(__down);
EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(securelevel);
/* all busmice */
EXPORT_SYMBOL(add_mouse_randomness);
diff --git a/kernel/printk.c b/kernel/printk.c
index afc178c5e..48922d779 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,7 @@ static char log_buf[LOG_BUF_LEN];
static unsigned long log_start = 0;
static unsigned long logged_chars = 0;
struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
-static int selected_console = 0;
+static int preferred_console = -1;
/*
* Setup a list of consoles. Called from init/main.c
@@ -95,11 +95,13 @@ __initfunc(void console_setup(char *str, int *ints))
*/
for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
if (strcmp(console_cmdline[i].name, name) == 0 &&
- console_cmdline[i].index == idx)
+ console_cmdline[i].index == idx) {
+ preferred_console = i;
return;
+ }
if (i == MAX_CMDLINECONSOLES)
return;
- selected_console = 1;
+ preferred_console = i;
c = &console_cmdline[i];
memcpy(c->name, name, sizeof(c->name));
c->options = options;
@@ -336,13 +338,13 @@ void register_console(struct console * console)
* didn't select a console we take the first one
* that registers here.
*/
- if (selected_console == 0) {
+ if (preferred_console < 0) {
if (console->index < 0)
console->index = 0;
if (console->setup == NULL ||
console->setup(console, NULL) == 0) {
- console->flags |= CON_ENABLED | CON_FIRST;
- selected_console = 1;
+ console->flags |= CON_ENABLED | CON_CONSDEV;
+ preferred_console = 0;
}
}
@@ -356,14 +358,15 @@ void register_console(struct console * console)
if (console->index >= 0 &&
console->index != console_cmdline[i].index)
continue;
- if (console->index < 0) console->index = 0;
+ if (console->index < 0)
+ console->index = console_cmdline[i].index;
if (console->setup &&
console->setup(console, console_cmdline[i].options) != 0)
break;
console->flags |= CON_ENABLED;
console->index = console_cmdline[i].index;
- if (i == 0)
- console->flags |= CON_FIRST;
+ if (i == preferred_console)
+ console->flags |= CON_CONSDEV;
break;
}
@@ -374,7 +377,7 @@ void register_console(struct console * console)
* Put this console in the list - keep the
* preferred driver at the head of the list.
*/
- if ((console->flags & CON_FIRST) || console_drivers == NULL) {
+ if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
console->next = console_drivers;
console_drivers = console;
} else {
diff --git a/kernel/sched.c b/kernel/sched.c
index 8d8576808..f9246e785 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -47,7 +47,7 @@
* kernel variables
*/
-int securelevel = 0; /* system security level */
+unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */
diff --git a/kernel/signal.c b/kernel/signal.c
index c313b0a11..f9145783e 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -788,6 +788,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
if (act) {
*k = *act;
+ sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
/*
* POSIX 3.3.1.3:
diff --git a/kernel/sys.c b/kernel/sys.c
index e86d18c09..aadb3ab5f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -177,7 +177,8 @@ asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg)
/* For safety, we require "magic" arguments. */
if (magic1 != LINUX_REBOOT_MAGIC1 ||
- (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A))
+ (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
+ magic2 != LINUX_REBOOT_MAGIC2B))
return -EINVAL;
lock_kernel();
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 47bb36171..27616bfee 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -33,7 +33,7 @@
#include <linux/nfs_fs.h>
#endif
-#ifdef CONFIG_SYSCTL
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
/* External variables not in a header file. */
extern int panic_timeout;
@@ -43,7 +43,9 @@ extern char binfmt_java_interpreter[], binfmt_java_appletviewer[];
extern int sysctl_overcommit_memory;
#ifdef CONFIG_KMOD
extern char modprobe_path[];
-extern int kmod_unload_delay;
+#endif
+#ifdef CONFIG_CHR_DEV_SG
+extern int sg_big_buff;
#endif
#ifdef __sparc__
@@ -52,8 +54,6 @@ extern char reboot_command [];
static int parse_table(int *, int, void *, size_t *, void *, size_t,
ctl_table *, void **);
-static int do_securelevel_strategy (ctl_table *, int *, int, void *, size_t *,
- void *, size_t, void **);
static ctl_table root_table[];
@@ -156,8 +156,6 @@ static ctl_table kern_table[] = {
0644, NULL, &proc_dointvec},
{KERN_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
0444, NULL, &proc_dointvec},
- {KERN_SECURELVL, "securelevel", &securelevel, sizeof(int),
- 0444, NULL, &proc_dointvec, (ctl_handler *)&do_securelevel_strategy},
{KERN_PANIC, "panic", &panic_timeout, sizeof(int),
0644, NULL, &proc_dointvec},
#ifdef CONFIG_BLK_DEV_INITRD
@@ -181,8 +179,10 @@ static ctl_table kern_table[] = {
#ifdef CONFIG_KMOD
{KERN_MODPROBE, "modprobe", &modprobe_path, 256,
0644, NULL, &proc_dostring, &sysctl_string },
- {KERN_KMOD_UNLOAD_DELAY, "kmod_unload_delay", &kmod_unload_delay,
- sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+#ifdef CONFIG_CHR_DEV_SG
+ {KERN_NRFILE, "sg-big-buff", &sg_big_buff, sizeof (int),
+ 0444, NULL, &proc_dointvec},
#endif
{0}
};
@@ -408,29 +408,6 @@ int do_sysctl_strategy (ctl_table *table,
return 0;
}
-/*
- * This function only checks permission for changing the security level
- * If the tests are successful, the actual change is done by
- * do_sysctl_strategy
- */
-static int do_securelevel_strategy (ctl_table *table,
- int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen, void **context)
-{
- int level;
-
- if (newval && newlen) {
- if (newlen != sizeof (int))
- return -EINVAL;
- if(copy_from_user (&level, newval, newlen))
- return -EFAULT;
- if (level < securelevel && current->pid != 1)
- return -EPERM;
- }
- return 0;
-}
-
struct ctl_table_header *register_sysctl_table(ctl_table * table,
int insert_at_head)
{
@@ -1031,7 +1008,7 @@ int do_struct (
}
-#else /* CONFIG_SYSCTL */
+#else /* CONFIG_PROC_FS && CONFIG_SYSCTL */
extern asmlinkage int sys_sysctl(struct __sysctl_args *args)
@@ -1087,7 +1064,7 @@ void unregister_sysctl_table(struct ctl_table_header * table)
{
}
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_PROC_FS && CONFIG_SYSCTL */