aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/litmus_proc.h6
-rw-r--r--litmus/litmus_proc.c66
2 files changed, 44 insertions, 28 deletions
diff --git a/include/litmus/litmus_proc.h b/include/litmus/litmus_proc.h
index fbc0082b2d21..6800e725d48c 100644
--- a/include/litmus/litmus_proc.h
+++ b/include/litmus/litmus_proc.h
@@ -17,3 +17,9 @@ long make_plugin_proc_dir(struct sched_plugin* plugin,
17 */ 17 */
18void remove_plugin_proc_dir(struct sched_plugin* plugin); 18void remove_plugin_proc_dir(struct sched_plugin* plugin);
19 19
20
21/* Copy at most size-1 bytes from ubuf into kbuf, null-terminate buf, and
22 * remove a '\n' if present. Returns the number of bytes that were read or
23 * -EFAULT. */
24int copy_and_chomp(char *kbuf, unsigned long ksize,
25 __user const char* ubuf, unsigned long ulength);
diff --git a/litmus/litmus_proc.c b/litmus/litmus_proc.c
index 81ea5c35d291..e3f3f11f80e1 100644
--- a/litmus/litmus_proc.c
+++ b/litmus/litmus_proc.c
@@ -69,18 +69,9 @@ static int proc_write_curr(struct file *file,
69 char name[65]; 69 char name[65];
70 struct sched_plugin* found; 70 struct sched_plugin* found;
71 71
72 if(count > 64) 72 len = copy_and_chomp(name, sizeof(name), buffer, count);
73 len = 64; 73 if (len < 0)
74 else 74 return len;
75 len = count;
76
77 if(copy_from_user(name, buffer, len))
78 return -EFAULT;
79
80 name[len] = '\0';
81 /* chomp name */
82 if (len > 1 && name[len - 1] == '\n')
83 name[len - 1] = '\0';
84 75
85 found = find_sched_plugin(name); 76 found = find_sched_plugin(name);
86 77
@@ -113,36 +104,28 @@ static int proc_write_release_master(struct file *file,
113 unsigned long count, 104 unsigned long count,
114 void *data) 105 void *data)
115{ 106{
116 int cpu, err, online = 0; 107 int cpu, err, len, online = 0;
117 char msg[64]; 108 char msg[64];
118 109
119 if (count > 63) 110 len = copy_and_chomp(msg, sizeof(msg), buffer, count);
120 return -EINVAL;
121
122 if (copy_from_user(msg, buffer, count))
123 return -EFAULT;
124 111
125 /* terminate */ 112 if (len < 0)
126 msg[count] = '\0'; 113 return len;
127 /* chomp */
128 if (count > 1 && msg[count - 1] == '\n')
129 msg[count - 1] = '\0';
130 114
131 if (strcmp(msg, "NO_CPU") == 0) { 115 if (strcmp(msg, "NO_CPU") == 0)
132 atomic_set(&release_master_cpu, NO_CPU); 116 atomic_set(&release_master_cpu, NO_CPU);
133 return count; 117 else {
134 } else {
135 err = sscanf(msg, "%d", &cpu); 118 err = sscanf(msg, "%d", &cpu);
136 if (err == 1 && cpu >= 0 && (online = cpu_online(cpu))) { 119 if (err == 1 && cpu >= 0 && (online = cpu_online(cpu))) {
137 atomic_set(&release_master_cpu, cpu); 120 atomic_set(&release_master_cpu, cpu);
138 return count;
139 } else { 121 } else {
140 TRACE("invalid release master: '%s' " 122 TRACE("invalid release master: '%s' "
141 "(err:%d cpu:%d online:%d)\n", 123 "(err:%d cpu:%d online:%d)\n",
142 msg, err, cpu, online); 124 msg, err, cpu, online);
143 return -EINVAL; 125 len = -EINVAL;
144 } 126 }
145 } 127 }
128 return len;
146} 129}
147#endif 130#endif
148 131
@@ -257,3 +240,30 @@ void remove_plugin_proc_dir(struct sched_plugin* plugin)
257 } 240 }
258 remove_proc_entry(plugin->plugin_name, plugs_dir); 241 remove_proc_entry(plugin->plugin_name, plugs_dir);
259} 242}
243
244
245
246/* misc. I/O helper functions */
247
248int copy_and_chomp(char *kbuf, unsigned long ksize,
249 __user const char* ubuf, unsigned long ulength)
250{
251 /* caller must provide buffer space */
252 BUG_ON(!ksize);
253
254 ksize--; /* leave space for null byte */
255
256 if (ksize > ulength)
257 ksize = ulength;
258
259 if(copy_from_user(kbuf, ubuf, ksize))
260 return -EFAULT;
261
262 kbuf[ksize] = '\0';
263
264 /* chomp kbuf */
265 if (ksize > 0 && kbuf[ksize - 1] == '\n')
266 kbuf[ksize - 1] = '\0';
267
268 return ksize;
269}