Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'uml-for-linus-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux

Pull UML fixes from Richard Weinberger:

- Align signal stack correctly

- Convert to raw spinlocks where needed (irq and virtio)

- FPU related fixes

* tag 'uml-for-linus-6.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux:
um: convert irq_lock to raw spinlock
um: virtio_uml: use raw spinlock
um: virt-pci: don't use kmalloc()
um: fix execve stub execution on old host OSs
um: properly align signal stack on x86_64
um: avoid copying FP state from init_task
um: add back support for FXSAVE registers

+202 -141
+101 -95
arch/um/drivers/virt-pci.c
··· 25 25 #define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32)) 26 26 #define NUM_IRQ_MSGS 10 27 27 28 - #define HANDLE_NO_FREE(ptr) ((void *)((unsigned long)(ptr) | 1)) 29 - #define HANDLE_IS_NO_FREE(ptr) ((unsigned long)(ptr) & 1) 28 + struct um_pci_message_buffer { 29 + struct virtio_pcidev_msg hdr; 30 + u8 data[8]; 31 + }; 30 32 31 33 struct um_pci_device { 32 34 struct virtio_device *vdev; ··· 37 35 u8 resptr[PCI_STD_NUM_BARS]; 38 36 39 37 struct virtqueue *cmd_vq, *irq_vq; 38 + 39 + #define UM_PCI_WRITE_BUFS 20 40 + struct um_pci_message_buffer bufs[UM_PCI_WRITE_BUFS + 1]; 41 + void *extra_ptrs[UM_PCI_WRITE_BUFS + 1]; 42 + DECLARE_BITMAP(used_bufs, UM_PCI_WRITE_BUFS); 40 43 41 44 #define UM_PCI_STAT_WAITING 0 42 45 unsigned long status; ··· 68 61 static unsigned int um_pci_max_delay_us = 40000; 69 62 module_param_named(max_delay_us, um_pci_max_delay_us, uint, 0644); 70 63 71 - struct um_pci_message_buffer { 72 - struct virtio_pcidev_msg hdr; 73 - u8 data[8]; 74 - }; 64 + static int um_pci_get_buf(struct um_pci_device *dev, bool *posted) 65 + { 66 + int i; 75 67 76 - static struct um_pci_message_buffer __percpu *um_pci_msg_bufs; 68 + for (i = 0; i < UM_PCI_WRITE_BUFS; i++) { 69 + if (!test_and_set_bit(i, dev->used_bufs)) 70 + return i; 71 + } 72 + 73 + *posted = false; 74 + return UM_PCI_WRITE_BUFS; 75 + } 76 + 77 + static void um_pci_free_buf(struct um_pci_device *dev, void *buf) 78 + { 79 + int i; 80 + 81 + if (buf == &dev->bufs[UM_PCI_WRITE_BUFS]) { 82 + kfree(dev->extra_ptrs[UM_PCI_WRITE_BUFS]); 83 + dev->extra_ptrs[UM_PCI_WRITE_BUFS] = NULL; 84 + return; 85 + } 86 + 87 + for (i = 0; i < UM_PCI_WRITE_BUFS; i++) { 88 + if (buf == &dev->bufs[i]) { 89 + kfree(dev->extra_ptrs[i]); 90 + dev->extra_ptrs[i] = NULL; 91 + WARN_ON(!test_and_clear_bit(i, dev->used_bufs)); 92 + return; 93 + } 94 + } 95 + 96 + WARN_ON(1); 97 + } 77 98 78 99 static int um_pci_send_cmd(struct um_pci_device *dev, 79 100 struct virtio_pcidev_msg *cmd, ··· 117 82 }; 118 83 struct um_pci_message_buffer *buf; 119 84 int delay_count = 0; 85 + bool bounce_out; 120 86 int ret, len; 87 + int buf_idx; 121 88 bool posted; 122 89 123 90 if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf))) ··· 138 101 break; 139 102 } 140 103 141 - buf = get_cpu_var(um_pci_msg_bufs); 142 - if (buf) 143 - memcpy(buf, cmd, cmd_size); 104 + bounce_out = !posted && cmd_size <= sizeof(*cmd) && 105 + out && out_size <= sizeof(buf->data); 144 106 145 - if (posted) { 146 - u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC); 107 + buf_idx = um_pci_get_buf(dev, &posted); 108 + buf = &dev->bufs[buf_idx]; 109 + memcpy(buf, cmd, cmd_size); 147 110 148 - if (ncmd) { 149 - memcpy(ncmd, cmd, cmd_size); 150 - if (extra) 151 - memcpy(ncmd + cmd_size, extra, extra_size); 152 - cmd = (void *)ncmd; 153 - cmd_size += extra_size; 154 - extra = NULL; 155 - extra_size = 0; 156 - } else { 157 - /* try without allocating memory */ 158 - posted = false; 159 - cmd = (void *)buf; 111 + if (posted && extra && extra_size > sizeof(buf) - cmd_size) { 112 + dev->extra_ptrs[buf_idx] = kmemdup(extra, extra_size, 113 + GFP_ATOMIC); 114 + 115 + if (!dev->extra_ptrs[buf_idx]) { 116 + um_pci_free_buf(dev, buf); 117 + return -ENOMEM; 160 118 } 119 + extra = dev->extra_ptrs[buf_idx]; 120 + } else if (extra && extra_size <= sizeof(buf) - cmd_size) { 121 + memcpy((u8 *)buf + cmd_size, extra, extra_size); 122 + cmd_size += extra_size; 123 + extra_size = 0; 124 + extra = NULL; 125 + cmd = (void *)buf; 161 126 } else { 162 127 cmd = (void *)buf; 163 128 } ··· 167 128 sg_init_one(&out_sg, cmd, cmd_size); 168 129 if (extra) 169 130 sg_init_one(&extra_sg, extra, extra_size); 170 - if (out) 131 + /* allow stack for small buffers */ 132 + if (bounce_out) 133 + sg_init_one(&in_sg, buf->data, out_size); 134 + else if (out) 171 135 sg_init_one(&in_sg, out, out_size); 172 136 173 137 /* add to internal virtio queue */ 174 138 ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, 175 139 extra ? 2 : 1, 176 140 out ? 1 : 0, 177 - posted ? cmd : HANDLE_NO_FREE(cmd), 178 - GFP_ATOMIC); 141 + cmd, GFP_ATOMIC); 179 142 if (ret) { 180 - if (posted) 181 - kfree(cmd); 182 - goto out; 143 + um_pci_free_buf(dev, buf); 144 + return ret; 183 145 } 184 146 185 147 if (posted) { 186 148 virtqueue_kick(dev->cmd_vq); 187 - ret = 0; 188 - goto out; 149 + return 0; 189 150 } 190 151 191 152 /* kick and poll for getting a response on the queue */ 192 153 set_bit(UM_PCI_STAT_WAITING, &dev->status); 193 154 virtqueue_kick(dev->cmd_vq); 155 + ret = 0; 194 156 195 157 while (1) { 196 158 void *completed = virtqueue_get_buf(dev->cmd_vq, &len); 197 159 198 - if (completed == HANDLE_NO_FREE(cmd)) 160 + if (completed == buf) 199 161 break; 200 162 201 - if (completed && !HANDLE_IS_NO_FREE(completed)) 202 - kfree(completed); 163 + if (completed) 164 + um_pci_free_buf(dev, completed); 203 165 204 166 if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || 205 167 ++delay_count > um_pci_max_delay_us, ··· 212 172 } 213 173 clear_bit(UM_PCI_STAT_WAITING, &dev->status); 214 174 215 - out: 216 - put_cpu_var(um_pci_msg_bufs); 175 + if (bounce_out) 176 + memcpy(out, buf->data, out_size); 177 + 178 + um_pci_free_buf(dev, buf); 179 + 217 180 return ret; 218 181 } 219 182 ··· 230 187 .size = size, 231 188 .addr = offset, 232 189 }; 233 - /* buf->data is maximum size - we may only use parts of it */ 234 - struct um_pci_message_buffer *buf; 235 - u8 *data; 236 - unsigned long ret = ULONG_MAX; 237 - size_t bytes = sizeof(buf->data); 190 + /* max 8, we might not use it all */ 191 + u8 data[8]; 238 192 239 193 if (!dev) 240 194 return ULONG_MAX; 241 195 242 - buf = get_cpu_var(um_pci_msg_bufs); 243 - data = buf->data; 244 - 245 - if (buf) 246 - memset(data, 0xff, bytes); 196 + memset(data, 0xff, sizeof(data)); 247 197 248 198 switch (size) { 249 199 case 1: ··· 248 212 break; 249 213 default: 250 214 WARN(1, "invalid config space read size %d\n", size); 251 - goto out; 215 + return ULONG_MAX; 252 216 } 253 217 254 - if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, bytes)) 255 - goto out; 218 + if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, size)) 219 + return ULONG_MAX; 256 220 257 221 switch (size) { 258 222 case 1: 259 - ret = data[0]; 260 - break; 223 + return data[0]; 261 224 case 2: 262 - ret = le16_to_cpup((void *)data); 263 - break; 225 + return le16_to_cpup((void *)data); 264 226 case 4: 265 - ret = le32_to_cpup((void *)data); 266 - break; 227 + return le32_to_cpup((void *)data); 267 228 #ifdef CONFIG_64BIT 268 229 case 8: 269 - ret = le64_to_cpup((void *)data); 270 - break; 230 + return le64_to_cpup((void *)data); 271 231 #endif 272 232 default: 273 - break; 233 + return ULONG_MAX; 274 234 } 275 - 276 - out: 277 - put_cpu_var(um_pci_msg_bufs); 278 - return ret; 279 235 } 280 236 281 237 static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size, ··· 340 312 static unsigned long um_pci_bar_read(void *priv, unsigned int offset, 341 313 int size) 342 314 { 343 - /* buf->data is maximum size - we may only use parts of it */ 344 - struct um_pci_message_buffer *buf; 345 - u8 *data; 346 - unsigned long ret = ULONG_MAX; 347 - 348 - buf = get_cpu_var(um_pci_msg_bufs); 349 - data = buf->data; 315 + /* 8 is maximum size - we may only use parts of it */ 316 + u8 data[8]; 350 317 351 318 switch (size) { 352 319 case 1: ··· 353 330 break; 354 331 default: 355 332 WARN(1, "invalid config space read size %d\n", size); 356 - goto out; 333 + return ULONG_MAX; 357 334 } 358 335 359 336 um_pci_bar_copy_from(priv, data, offset, size); 360 337 361 338 switch (size) { 362 339 case 1: 363 - ret = data[0]; 364 - break; 340 + return data[0]; 365 341 case 2: 366 - ret = le16_to_cpup((void *)data); 367 - break; 342 + return le16_to_cpup((void *)data); 368 343 case 4: 369 - ret = le32_to_cpup((void *)data); 370 - break; 344 + return le32_to_cpup((void *)data); 371 345 #ifdef CONFIG_64BIT 372 346 case 8: 373 - ret = le64_to_cpup((void *)data); 374 - break; 347 + return le64_to_cpup((void *)data); 375 348 #endif 376 349 default: 377 - break; 350 + return ULONG_MAX; 378 351 } 379 - 380 - out: 381 - put_cpu_var(um_pci_msg_bufs); 382 - return ret; 383 352 } 384 353 385 354 static void um_pci_bar_copy_to(void *priv, unsigned int offset, ··· 538 523 if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) 539 524 return; 540 525 541 - while ((cmd = virtqueue_get_buf(vq, &len))) { 542 - if (WARN_ON(HANDLE_IS_NO_FREE(cmd))) 543 - continue; 544 - kfree(cmd); 545 - } 526 + while ((cmd = virtqueue_get_buf(vq, &len))) 527 + um_pci_free_buf(dev, cmd); 546 528 } 547 529 548 530 static void um_pci_irq_vq_cb(struct virtqueue *vq) ··· 1018 1006 "No virtio device ID configured for PCI - no PCI support\n")) 1019 1007 return 0; 1020 1008 1021 - um_pci_msg_bufs = alloc_percpu(struct um_pci_message_buffer); 1022 - if (!um_pci_msg_bufs) 1023 - return -ENOMEM; 1024 - 1025 1009 bridge = pci_alloc_host_bridge(0); 1026 1010 if (!bridge) { 1027 1011 err = -ENOMEM; ··· 1078 1070 pci_free_resource_list(&bridge->windows); 1079 1071 pci_free_host_bridge(bridge); 1080 1072 } 1081 - free_percpu(um_pci_msg_bufs); 1082 1073 return err; 1083 1074 } 1084 1075 module_init(um_pci_init); ··· 1089 1082 irq_domain_remove(um_pci_inner_domain); 1090 1083 pci_free_resource_list(&bridge->windows); 1091 1084 pci_free_host_bridge(bridge); 1092 - free_percpu(um_pci_msg_bufs); 1093 1085 } 1094 1086 module_exit(um_pci_exit);
+4 -4
arch/um/drivers/virtio_uml.c
··· 52 52 struct platform_device *pdev; 53 53 struct virtio_uml_platform_data *pdata; 54 54 55 - spinlock_t sock_lock; 55 + raw_spinlock_t sock_lock; 56 56 int sock, req_fd, irq; 57 57 u64 features; 58 58 u64 protocol_features; ··· 246 246 if (request_ack) 247 247 msg->header.flags |= VHOST_USER_FLAG_NEED_REPLY; 248 248 249 - spin_lock_irqsave(&vu_dev->sock_lock, flags); 249 + raw_spin_lock_irqsave(&vu_dev->sock_lock, flags); 250 250 rc = full_sendmsg_fds(vu_dev->sock, msg, size, fds, num_fds); 251 251 if (rc < 0) 252 252 goto out; ··· 266 266 } 267 267 268 268 out: 269 - spin_unlock_irqrestore(&vu_dev->sock_lock, flags); 269 + raw_spin_unlock_irqrestore(&vu_dev->sock_lock, flags); 270 270 return rc; 271 271 } 272 272 ··· 1239 1239 goto error_free; 1240 1240 vu_dev->sock = rc; 1241 1241 1242 - spin_lock_init(&vu_dev->sock_lock); 1242 + raw_spin_lock_init(&vu_dev->sock_lock); 1243 1243 1244 1244 rc = vhost_user_init(vu_dev); 1245 1245 if (rc)
+47 -32
arch/um/kernel/irq.c
··· 52 52 bool sigio_workaround; 53 53 }; 54 54 55 - static DEFINE_SPINLOCK(irq_lock); 55 + static DEFINE_RAW_SPINLOCK(irq_lock); 56 56 static LIST_HEAD(active_fds); 57 57 static DECLARE_BITMAP(irqs_allocated, UM_LAST_SIGNAL_IRQ); 58 58 static bool irqs_suspended; ··· 257 257 return NULL; 258 258 } 259 259 260 - static void free_irq_entry(struct irq_entry *to_free, bool remove) 260 + static void remove_irq_entry(struct irq_entry *to_free, bool remove) 261 261 { 262 262 if (!to_free) 263 263 return; ··· 265 265 if (remove) 266 266 os_del_epoll_fd(to_free->fd); 267 267 list_del(&to_free->list); 268 - kfree(to_free); 269 268 } 270 269 271 270 static bool update_irq_entry(struct irq_entry *entry) ··· 285 286 return false; 286 287 } 287 288 288 - static void update_or_free_irq_entry(struct irq_entry *entry) 289 + static struct irq_entry *update_or_remove_irq_entry(struct irq_entry *entry) 289 290 { 290 - if (!update_irq_entry(entry)) 291 - free_irq_entry(entry, false); 291 + if (update_irq_entry(entry)) 292 + return NULL; 293 + remove_irq_entry(entry, false); 294 + return entry; 292 295 } 293 296 294 297 static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, 295 298 void (*timetravel_handler)(int, int, void *, 296 299 struct time_travel_event *)) 297 300 { 298 - struct irq_entry *irq_entry; 301 + struct irq_entry *irq_entry, *to_free = NULL; 299 302 int err, events = os_event_mask(type); 300 303 unsigned long flags; 301 304 ··· 305 304 if (err < 0) 306 305 goto out; 307 306 308 - spin_lock_irqsave(&irq_lock, flags); 307 + raw_spin_lock_irqsave(&irq_lock, flags); 309 308 irq_entry = get_irq_entry_by_fd(fd); 310 309 if (irq_entry) { 310 + already: 311 311 /* cannot register the same FD twice with the same type */ 312 312 if (WARN_ON(irq_entry->reg[type].events)) { 313 313 err = -EALREADY; ··· 318 316 /* temporarily disable to avoid IRQ-side locking */ 319 317 os_del_epoll_fd(fd); 320 318 } else { 321 - irq_entry = kzalloc(sizeof(*irq_entry), GFP_ATOMIC); 322 - if (!irq_entry) { 323 - err = -ENOMEM; 324 - goto out_unlock; 319 + struct irq_entry *new; 320 + 321 + /* don't restore interrupts */ 322 + raw_spin_unlock(&irq_lock); 323 + new = kzalloc(sizeof(*irq_entry), GFP_ATOMIC); 324 + if (!new) { 325 + local_irq_restore(flags); 326 + return -ENOMEM; 325 327 } 328 + raw_spin_lock(&irq_lock); 329 + irq_entry = get_irq_entry_by_fd(fd); 330 + if (irq_entry) { 331 + to_free = new; 332 + goto already; 333 + } 334 + irq_entry = new; 326 335 irq_entry->fd = fd; 327 336 list_add_tail(&irq_entry->list, &active_fds); 328 337 maybe_sigio_broken(fd); ··· 352 339 #endif 353 340 354 341 WARN_ON(!update_irq_entry(irq_entry)); 355 - spin_unlock_irqrestore(&irq_lock, flags); 356 - 357 - return 0; 342 + err = 0; 358 343 out_unlock: 359 - spin_unlock_irqrestore(&irq_lock, flags); 344 + raw_spin_unlock_irqrestore(&irq_lock, flags); 360 345 out: 346 + kfree(to_free); 361 347 return err; 362 348 } 363 349 ··· 370 358 struct irq_entry *to_free; 371 359 unsigned long flags; 372 360 373 - spin_lock_irqsave(&irq_lock, flags); 361 + raw_spin_lock_irqsave(&irq_lock, flags); 374 362 to_free = get_irq_entry_by_fd(fd); 375 - free_irq_entry(to_free, true); 376 - spin_unlock_irqrestore(&irq_lock, flags); 363 + remove_irq_entry(to_free, true); 364 + raw_spin_unlock_irqrestore(&irq_lock, flags); 365 + kfree(to_free); 377 366 } 378 367 EXPORT_SYMBOL(free_irq_by_fd); 379 368 380 369 static void free_irq_by_irq_and_dev(unsigned int irq, void *dev) 381 370 { 382 - struct irq_entry *entry; 371 + struct irq_entry *entry, *to_free = NULL; 383 372 unsigned long flags; 384 373 385 - spin_lock_irqsave(&irq_lock, flags); 374 + raw_spin_lock_irqsave(&irq_lock, flags); 386 375 list_for_each_entry(entry, &active_fds, list) { 387 376 enum um_irq_type i; 388 377 ··· 399 386 400 387 os_del_epoll_fd(entry->fd); 401 388 reg->events = 0; 402 - update_or_free_irq_entry(entry); 389 + to_free = update_or_remove_irq_entry(entry); 403 390 goto out; 404 391 } 405 392 } 406 393 out: 407 - spin_unlock_irqrestore(&irq_lock, flags); 394 + raw_spin_unlock_irqrestore(&irq_lock, flags); 395 + kfree(to_free); 408 396 } 409 397 410 398 void deactivate_fd(int fd, int irqnum) ··· 416 402 417 403 os_del_epoll_fd(fd); 418 404 419 - spin_lock_irqsave(&irq_lock, flags); 405 + raw_spin_lock_irqsave(&irq_lock, flags); 420 406 entry = get_irq_entry_by_fd(fd); 421 407 if (!entry) 422 408 goto out; ··· 428 414 entry->reg[i].events = 0; 429 415 } 430 416 431 - update_or_free_irq_entry(entry); 417 + entry = update_or_remove_irq_entry(entry); 432 418 out: 433 - spin_unlock_irqrestore(&irq_lock, flags); 419 + raw_spin_unlock_irqrestore(&irq_lock, flags); 420 + kfree(entry); 434 421 435 422 ignore_sigio_fd(fd); 436 423 } ··· 561 546 562 547 irqs_suspended = true; 563 548 564 - spin_lock_irqsave(&irq_lock, flags); 549 + raw_spin_lock_irqsave(&irq_lock, flags); 565 550 list_for_each_entry(entry, &active_fds, list) { 566 551 enum um_irq_type t; 567 552 bool clear = true; ··· 594 579 !__ignore_sigio_fd(entry->fd); 595 580 } 596 581 } 597 - spin_unlock_irqrestore(&irq_lock, flags); 582 + raw_spin_unlock_irqrestore(&irq_lock, flags); 598 583 } 599 584 600 585 void um_irqs_resume(void) ··· 603 588 unsigned long flags; 604 589 605 590 606 - spin_lock_irqsave(&irq_lock, flags); 591 + raw_spin_lock_irqsave(&irq_lock, flags); 607 592 list_for_each_entry(entry, &active_fds, list) { 608 593 if (entry->suspended) { 609 594 int err = os_set_fd_async(entry->fd); ··· 617 602 } 618 603 } 619 604 } 620 - spin_unlock_irqrestore(&irq_lock, flags); 605 + raw_spin_unlock_irqrestore(&irq_lock, flags); 621 606 622 607 irqs_suspended = false; 623 608 send_sigio_to_self(); ··· 628 613 struct irq_entry *entry; 629 614 unsigned long flags; 630 615 631 - spin_lock_irqsave(&irq_lock, flags); 616 + raw_spin_lock_irqsave(&irq_lock, flags); 632 617 list_for_each_entry(entry, &active_fds, list) { 633 618 enum um_irq_type t; 634 619 ··· 643 628 } 644 629 } 645 630 unlock: 646 - spin_unlock_irqrestore(&irq_lock, flags); 631 + raw_spin_unlock_irqrestore(&irq_lock, flags); 647 632 return 0; 648 633 } 649 634 #else
+9 -1
arch/um/kernel/process.c
··· 191 191 int arch_dup_task_struct(struct task_struct *dst, 192 192 struct task_struct *src) 193 193 { 194 - memcpy(dst, src, arch_task_struct_size); 194 + /* init_task is not dynamically sized (missing FPU state) */ 195 + if (unlikely(src == &init_task)) { 196 + memcpy(dst, src, sizeof(init_task)); 197 + memset((void *)dst + sizeof(init_task), 0, 198 + arch_task_struct_size - sizeof(init_task)); 199 + } else { 200 + memcpy(dst, src, arch_task_struct_size); 201 + } 202 + 195 203 return 0; 196 204 } 197 205
+13 -3
arch/um/os-Linux/skas/process.c
··· 181 181 182 182 static int stub_exe_fd; 183 183 184 + #ifndef CLOSE_RANGE_CLOEXEC 185 + #define CLOSE_RANGE_CLOEXEC (1U << 2) 186 + #endif 187 + 184 188 static int userspace_tramp(void *stack) 185 189 { 186 190 char *const argv[] = { "uml-userspace", NULL }; ··· 206 202 init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset); 207 203 init_data.stub_data_offset = MMAP_OFFSET(offset); 208 204 209 - /* Set CLOEXEC on all FDs and then unset on all memory related FDs */ 210 - close_range(0, ~0U, CLOSE_RANGE_CLOEXEC); 205 + /* 206 + * Avoid leaking unneeded FDs to the stub by setting CLOEXEC on all FDs 207 + * and then unsetting it on all memory related FDs. 208 + * This is not strictly necessary from a safety perspective. 209 + */ 210 + syscall(__NR_close_range, 0, ~0U, CLOSE_RANGE_CLOEXEC); 211 211 212 212 fcntl(init_data.stub_data_fd, F_SETFD, 0); 213 213 for (iomem = iomem_regions; iomem; iomem = iomem->next) ··· 232 224 if (ret != sizeof(init_data)) 233 225 exit(4); 234 226 235 - execveat(stub_exe_fd, "", argv, NULL, AT_EMPTY_PATH); 227 + /* Raw execveat for compatibility with older libc versions */ 228 + syscall(__NR_execveat, stub_exe_fd, (unsigned long)"", 229 + (unsigned long)argv, NULL, AT_EMPTY_PATH); 236 230 237 231 exit(5); 238 232 }
+18 -3
arch/x86/um/os-Linux/registers.c
··· 18 18 #include <registers.h> 19 19 #include <sys/mman.h> 20 20 21 + static unsigned long ptrace_regset; 21 22 unsigned long host_fp_size; 22 23 23 24 int get_fp_registers(int pid, unsigned long *regs) ··· 28 27 .iov_len = host_fp_size, 29 28 }; 30 29 31 - if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 30 + if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0) 32 31 return -errno; 33 32 return 0; 34 33 } ··· 40 39 .iov_len = host_fp_size, 41 40 }; 42 41 43 - if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 42 + if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0) 44 43 return -errno; 45 44 return 0; 46 45 } ··· 59 58 return -ENOMEM; 60 59 61 60 /* GDB has x86_xsave_length, which uses x86_cpuid_count */ 62 - ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov); 61 + ptrace_regset = NT_X86_XSTATE; 62 + ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); 63 63 if (ret) 64 64 ret = -errno; 65 + 66 + if (ret == -ENODEV) { 67 + #ifdef CONFIG_X86_32 68 + ptrace_regset = NT_PRXFPREG; 69 + #else 70 + ptrace_regset = NT_PRFPREG; 71 + #endif 72 + iov.iov_len = 2 * 1024 * 1024; 73 + ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); 74 + if (ret) 75 + ret = -errno; 76 + } 77 + 65 78 munmap(iov.iov_base, 2 * 1024 * 1024); 66 79 67 80 host_fp_size = iov.iov_len;
+10 -3
arch/x86/um/signal.c
··· 187 187 * Put magic/size values for userspace. We do not bother to verify them 188 188 * later on, however, userspace needs them should it try to read the 189 189 * XSTATE data. And ptrace does not fill in these parts. 190 + * 191 + * Skip this if we do not have an XSTATE frame. 190 192 */ 193 + if (host_fp_size <= sizeof(to_fp64->fpstate)) 194 + return 0; 195 + 191 196 BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE); 192 197 #ifdef CONFIG_X86_32 193 198 __put_user(offsetof(struct _fpstate_32, _fxsr_env) + ··· 372 367 int err = 0, sig = ksig->sig; 373 368 unsigned long fp_to; 374 369 375 - frame = (struct rt_sigframe __user *) 376 - round_down(stack_top - sizeof(struct rt_sigframe), 16); 370 + frame = (void __user *)stack_top - sizeof(struct rt_sigframe); 377 371 378 372 /* Add required space for math frame */ 379 - frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size); 373 + frame = (void __user *)((unsigned long)frame - math_size); 374 + 375 + /* ABI requires 16 byte boundary alignment */ 376 + frame = (void __user *)round_down((unsigned long)frame, 16); 380 377 381 378 /* Subtract 128 for a red zone and 8 for proper alignment */ 382 379 frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);