/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* This file contains machine independent code for performing core dumps.
*
- * HISTORY
- * 16-Feb-91 Mike DeMoney (mike@next.com)
- * Massaged into MI form from m68k/core.c.
*/
#include <mach/vm_param.h>
mythread_state_flavor_t thread_flavor_array[]={
{PPC_THREAD_STATE , PPC_THREAD_STATE_COUNT},
{PPC_FLOAT_STATE, PPC_FLOAT_STATE_COUNT},
- {PPC_EXCEPTION_STATE, PPC_EXCEPTION_STATE_COUNT}
+ {PPC_EXCEPTION_STATE, PPC_EXCEPTION_STATE_COUNT},
+ {PPC_VECTOR_STATE, PPC_VECTOR_STATE_COUNT}
};
-int mynum_flavors=3;
+int mynum_flavors=4;
#elif defined (__i386__)
mythread_state_flavor_t thread_flavor_array [] = {
{i386_THREAD_STATE, i386_THREAD_STATE_COUNT},
int tstate_size;
} tir_t;
+/* XXX should be static */
+void collectth_state(thread_act_t th_act, tir_t *t);
+
+/* XXX not in a Mach header anywhere */
+kern_return_t thread_getstatus(register thread_act_t act, int flavor,
+ thread_state_t tstate, mach_msg_type_number_t *count);
+
+
+__private_extern__ do_coredump = 1; /* default: dump cores */
+__private_extern__ sugid_coredump = 0; /* deafult: but not on SGUID binaries */
+
+void
collectth_state(thread_act_t th_act, tir_t *t)
{
vm_offset_t header;
flavors[i];
hoffset += sizeof(mythread_state_flavor_t);
thread_getstatus(th_act, flavors[i].flavor,
- (thread_state_t *)(header+hoffset),
+ (thread_state_t)(header+hoffset),
&flavors[i].count);
hoffset += flavors[i].count*sizeof(int);
}
t->hoffset = hoffset;
}
+
+extern boolean_t coredumpok(vm_map_t map, vm_offset_t va); /* temp fix */
+extern task_t current_task(void); /* XXX */
+
/*
* Create a core image on the file "core".
*/
#define MAX_TSTATE_FLAVORS 10
int
-coredump(p)
- register struct proc *p;
+coredump(struct proc *p)
{
int error=0;
register struct pcred *pcred = p->p_cred;
struct machine_slot *ms;
struct mach_header *mh;
struct segment_command *sc;
- struct thread_command *tc;
vm_size_t size;
vm_prot_t prot;
vm_prot_t maxprot;
vm_inherit_t inherit;
- vm_offset_t offset;
int error1;
task_t task;
char core_name[MAXCOMLEN+6];
+ char *name;
mythread_state_flavor_t flavors[MAX_TSTATE_FLAVORS];
- vm_size_t nflavors,mapsize;
+ vm_size_t mapsize;
int i;
int nesting_depth = 0;
kern_return_t kret;
int vbrcount=0;
tir_t tir1;
struct vnode * vp;
- extern boolean_t coredumpok(vm_map_t map, vm_offset_t va); /* temp fix */
- if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid)
+ if (do_coredump == 0 || /* Not dumping at all */
+ ( (sugid_coredump == 0) && /* Not dumping SUID/SGID binaries */
+ ( (pcred->p_svuid != pcred->p_ruid) ||
+ (pcred->p_svgid != pcred->p_rgid)))) {
+
return (EFAULT);
+ }
task = current_task();
map = current_map();
return (EFAULT);
(void) task_suspend(task);
+ /* create name according to sysctl'able format string */
+ name = proc_core_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
+
+ /* if name creation fails, fall back to historical behaviour... */
+ if (name == NULL) {
sprintf(core_name, "/cores/core.%d", p->p_pid);
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, core_name, p);
- if(error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR ))
+ name = core_name;
+ }
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
+ if((error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR )) != 0)
return (error);
vp = nd.ni_vp;
thread_count = get_task_numacts(task);
segment_count = get_vmmap_entries(map); /* XXX */
- /*
- * nflavors here is really the number of ints in flavors
- * to meet the thread_getstatus() calling convention
- */
-#if 0
- nflavors = sizeof(flavors)/sizeof(int);
- if (thread_getstatus(current_thread(), THREAD_STATE_FLAVOR_LIST,
- (thread_state_t)(flavors),
- &nflavors) != KERN_SUCCESS)
- panic("core flavor list");
- /* now convert to number of flavors */
- nflavors /= sizeof(mythread_state_flavor_t)/sizeof(int);
-#else
- nflavors = mynum_flavors;
bcopy(thread_flavor_array,flavors,sizeof(thread_flavor_array));
-#endif
tstate_size = 0;
- for (i = 0; i < nflavors; i++)
+ for (i = 0; i < mynum_flavors; i++)
tstate_size += sizeof(mythread_state_flavor_t) +
(flavors[i].count * sizeof(int));
mh->sizeofcmds = command_size;
hoffset = sizeof(struct mach_header); /* offset into header */
- foffset = round_page(header_size); /* offset into file */
+ foffset = round_page_32(header_size); /* offset into file */
vmoffset = VM_MIN_ADDRESS; /* offset into VM */
- /* We use to check for an error, here, now we try and get
+ /*
+ * We use to check for an error, here, now we try and get
* as much as we can
*/
while (segment_count > 0){
* Note: if we can't read, then we end up with
* a hole in the file.
*/
- if ((maxprot & VM_PROT_READ) == VM_PROT_READ && vbr.user_tag != VM_MEMORY_IOKIT && coredumpok(map,vmoffset)) {
+ if ((maxprot & VM_PROT_READ) == VM_PROT_READ
+ && vbr.user_tag != VM_MEMORY_IOKIT
+ && coredumpok(map,vmoffset)) {
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)vmoffset, size, foffset,
UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p);
}
segment_count--;
}
-#if 0 /* [ */
- task_lock(task);
- thread = (thread_t) queue_first(&task->thread_list);
- while (thread_count > 0) {
- /*
- * Fill in thread command structure.
- */
- tc = (struct thread_command *) (header + hoffset);
- tc->cmd = LC_THREAD;
- tc->cmdsize = sizeof(struct thread_command)
- + tstate_size;
- hoffset += sizeof(struct thread_command);
- /*
- * Follow with a struct thread_state_flavor and
- * the appropriate thread state struct for each
- * thread state flavor.
- */
- for (i = 0; i < nflavors; i++) {
- *(mythread_state_flavor_t *)(header+hoffset) =
- flavors[i];
- hoffset += sizeof(mythread_state_flavor_t);
- thread_getstatus(thread, flavors[i].flavor,
- (thread_state_t *)(header+hoffset),
- &flavors[i].count);
- hoffset += flavors[i].count*sizeof(int);
- }
- thread = (thread_t) queue_next(&thread->thread_list);
- thread_count--;
- }
- task_unlock(task);
-#else /* /* 0 ][ */
tir1.header = header;
tir1.hoffset = hoffset;
tir1.flavors = flavors;
tir1.tstate_size = tstate_size;
task_act_iterate_wth_args(task, collectth_state,&tir1);
-#endif /* 0 ] */
/*
* Write out the Mach header at the beginning of the
* file.
error1 = vn_close(vp, FWRITE, cred, p);
if (error == 0)
error = error1;
+ return (error);
}