hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/kernel/rseq.c
....@@ -120,8 +120,13 @@
120120 u32 sig;
121121 int ret;
122122
123
- if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
123
+#ifdef CONFIG_64BIT
124
+ if (get_user(ptr, &t->rseq->rseq_cs))
124125 return -EFAULT;
126
+#else
127
+ if (copy_from_user(&ptr, &t->rseq->rseq_cs, sizeof(ptr)))
128
+ return -EFAULT;
129
+#endif
125130 if (!ptr) {
126131 memset(rseq_cs, 0, sizeof(*rseq_cs));
127132 return 0;
....@@ -204,9 +209,13 @@
204209 *
205210 * Set rseq_cs to NULL.
206211 */
207
- if (clear_user(&t->rseq->rseq_cs.ptr64, sizeof(t->rseq->rseq_cs.ptr64)))
212
+#ifdef CONFIG_64BIT
213
+ return put_user(0UL, &t->rseq->rseq_cs);
214
+#else
215
+ if (clear_user(&t->rseq->rseq_cs, sizeof(t->rseq->rseq_cs)))
208216 return -EFAULT;
209217 return 0;
218
+#endif
210219 }
211220
212221 /*
....@@ -254,8 +263,7 @@
254263 * - signal delivery,
255264 * and return to user-space.
256265 *
257
- * This is how we can ensure that the entire rseq critical section,
258
- * consisting of both the C part and the assembly instruction sequence,
266
+ * This is how we can ensure that the entire rseq critical section
259267 * will issue the commit instruction only if executed atomically with
260268 * respect to other threads scheduled on the same CPU, and with respect
261269 * to signal handlers.
....@@ -267,18 +275,25 @@
267275
268276 if (unlikely(t->flags & PF_EXITING))
269277 return;
270
- if (unlikely(!access_ok(VERIFY_WRITE, t->rseq, sizeof(*t->rseq))))
278
+ if (unlikely(!access_ok(t->rseq, sizeof(*t->rseq))))
271279 goto error;
272
- ret = rseq_ip_fixup(regs);
273
- if (unlikely(ret < 0))
274
- goto error;
280
+ /*
281
+ * regs is NULL if and only if the caller is in a syscall path. Skip
282
+ * fixup and leave rseq_cs as is so that rseq_sycall() will detect and
283
+ * kill a misbehaving userspace on debug kernels.
284
+ */
285
+ if (regs) {
286
+ ret = rseq_ip_fixup(regs);
287
+ if (unlikely(ret < 0))
288
+ goto error;
289
+ }
275290 if (unlikely(rseq_update_cpu_id(t)))
276291 goto error;
277292 return;
278293
279294 error:
280295 sig = ksig ? ksig->sig : 0;
281
- force_sigsegv(sig, t);
296
+ force_sigsegv(sig);
282297 }
283298
284299 #ifdef CONFIG_DEBUG_RSEQ
....@@ -295,9 +310,9 @@
295310
296311 if (!t->rseq)
297312 return;
298
- if (!access_ok(VERIFY_READ, t->rseq, sizeof(*t->rseq)) ||
313
+ if (!access_ok(t->rseq, sizeof(*t->rseq)) ||
299314 rseq_get_rseq_cs(t, &rseq_cs) || in_rseq_cs(ip, &rseq_cs))
300
- force_sig(SIGSEGV, t);
315
+ force_sig(SIGSEGV);
301316 }
302317
303318 #endif
....@@ -311,10 +326,12 @@
311326 int ret;
312327
313328 if (flags & RSEQ_FLAG_UNREGISTER) {
329
+ if (flags & ~RSEQ_FLAG_UNREGISTER)
330
+ return -EINVAL;
314331 /* Unregister rseq for current thread. */
315332 if (current->rseq != rseq || !current->rseq)
316333 return -EINVAL;
317
- if (current->rseq_len != rseq_len)
334
+ if (rseq_len != sizeof(*rseq))
318335 return -EINVAL;
319336 if (current->rseq_sig != sig)
320337 return -EPERM;
....@@ -322,7 +339,6 @@
322339 if (ret)
323340 return ret;
324341 current->rseq = NULL;
325
- current->rseq_len = 0;
326342 current->rseq_sig = 0;
327343 return 0;
328344 }
....@@ -336,7 +352,7 @@
336352 * the provided address differs from the prior
337353 * one.
338354 */
339
- if (current->rseq != rseq || current->rseq_len != rseq_len)
355
+ if (current->rseq != rseq || rseq_len != sizeof(*rseq))
340356 return -EINVAL;
341357 if (current->rseq_sig != sig)
342358 return -EPERM;
....@@ -351,10 +367,9 @@
351367 if (!IS_ALIGNED((unsigned long)rseq, __alignof__(*rseq)) ||
352368 rseq_len != sizeof(*rseq))
353369 return -EINVAL;
354
- if (!access_ok(VERIFY_WRITE, rseq, rseq_len))
370
+ if (!access_ok(rseq, rseq_len))
355371 return -EFAULT;
356372 current->rseq = rseq;
357
- current->rseq_len = rseq_len;
358373 current->rseq_sig = sig;
359374 /*
360375 * If rseq was previously inactive, and has just been