Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / tux / cgi.c
1 /*
2  * TUX - Integrated Application Protocols Layer and Object Cache
3  *
4  * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
5  *
6  * cgi.c: user-space CGI (and other) code execution.
7  */
8
9 #define __KERNEL_SYSCALLS__
10 #define __KERNEL_SYSCALLS_NO_ERRNO__
11
12 #include <net/tux.h>
13
14 /****************************************************************
15  *      This program is free software; you can redistribute it and/or modify
16  *      it under the terms of the GNU General Public License as published by
17  *      the Free Software Foundation; either version 2, or (at your option)
18  *      any later version.
19  *
20  *      This program is distributed in the hope that it will be useful,
21  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *      GNU General Public License for more details.
24  *
25  *      You should have received a copy of the GNU General Public License
26  *      along with this program; if not, write to the Free Software
27  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28  *
29  ****************************************************************/
30
31 static int exec_usermode(char *program_path, char *argv[], char *envp[])
32 {
33         struct files_struct *files = current->files;
34         struct fdtable *fdt;
35         int i, err;
36
37         err = tux_chroot(tux_cgiroot);
38         if (err) {
39                 printk(KERN_ERR "TUX: CGI chroot returned %d, /proc/sys/net/tux/cgiroot is probably set up incorrectly! Aborting CGI execution.\n", err);
40                 return err;
41         }
42
43         /* Allow execve args to be in kernel space. */
44         set_fs(KERNEL_DS);
45
46         // TODO: is this RCU-safe?
47         spin_lock(&files->file_lock);
48         fdt = files_fdtable(files);
49         spin_unlock(&files->file_lock);
50
51         for (i = 3; i < fdt->max_fds; i++ )
52                 if (fdt->fd[i])
53                         tux_close(i);
54
55         err = __exec_usermodehelper(program_path, argv, envp, NULL);
56         if (err < 0)
57                 return err;
58         return 0;
59 }
60
61 static inline long tux_dup(unsigned int fildes)
62 {
63         int ret = -EBADF;
64         struct file * file = fget(fildes);
65
66         if (file)
67                 ret = dupfd(file, 0);
68         return ret;
69 }
70
71 static int exec_helper (void * data)
72 {
73         exec_param_t *param = data;
74         char **tmp;
75         int ret;
76
77         sprintf(current->comm,"doexec - %d", current->pid);
78 #ifdef CONFIG_SMP
79         if (!tux_cgi_inherit_cpu) {
80                 cpumask_t map;
81
82                 cpus_and(map, cpu_online_map, tux_cgi_cpu_mask);
83
84                 if (!(cpus_empty(map)))
85                         set_cpus_allowed(current, map);
86                 else
87                         set_cpus_allowed(current, cpu_online_map);
88         }
89 #endif
90
91         if (!param)
92                 TUX_BUG();
93         Dprintk("doing exec(%s).\n", param->command);
94
95         Dprintk("argv: ");
96         tmp = param->argv;
97         while (*tmp) {
98                 Dprintk("{%s} ", *tmp);
99                 tmp++;
100         }
101         Dprintk("\n");
102         Dprintk("envp: ");
103         tmp = param->envp;
104         while (*tmp) {
105                 Dprintk("{%s} ", *tmp);
106                 tmp++;
107         }
108         Dprintk("\n");
109         /*
110          * Set up stdin, stdout and stderr of the external
111          * CGI application.
112          */
113         if (param->pipe_fds) {
114                 struct files_struct *files = current->files;
115                 struct fdtable *fdt;
116
117                 tux_close(1);
118                 tux_close(2);
119                 tux_close(4);
120                 if (tux_dup(3) != 1)
121                         TUX_BUG();
122                 if (tux_dup(5) != 2)
123                         TUX_BUG();
124                 tux_close(3);
125                 tux_close(5);
126                 // do not close on exec.
127                 spin_lock(&files->file_lock);
128                 fdt = files_fdtable(files);
129                 FD_CLR(0, fdt->close_on_exec);
130                 FD_CLR(1, fdt->close_on_exec);
131                 FD_CLR(2, fdt->close_on_exec);
132                 spin_unlock(&files->file_lock);
133         }
134         ret = exec_usermode(param->command, param->argv, param->envp);
135         if (ret < 0)
136                 Dprintk("bug: exec() returned %d.\n", ret);
137         else
138                 Dprintk("exec()-ed successfully!\n");
139         return 0;
140 }
141
142 pid_t tux_exec_process (char *command, char **argv,
143                         char **envp, int pipe_fds,
144                                 exec_param_t *param, int wait)
145 {
146         exec_param_t param_local;
147         pid_t pid;
148         struct k_sigaction *ka;
149
150         ka = current->sighand->action + SIGCHLD-1;
151         ka->sa.sa_handler = SIG_IGN;
152
153         if (!param && wait)
154                 param = &param_local;
155
156         param->command = command;
157         param->argv = argv;
158         param->envp = envp;
159         param->pipe_fds = pipe_fds;
160
161 repeat_fork:
162         pid = kernel_thread(exec_helper, (void*) param, CLONE_SIGHAND|SIGCHLD);
163         Dprintk("kernel thread created PID %d.\n", pid);
164         if (pid < 0) {
165                 printk(KERN_ERR "TUX: could not create new CGI kernel thread due to %d... retrying.\n", pid);
166                 current->state = TASK_UNINTERRUPTIBLE;
167                 schedule_timeout(HZ);
168                 goto repeat_fork;
169         }
170         return pid;
171 }