/proc/sys/kernel/corename pre-patch

Michael Shields (simius@algonet.se)
Tue, 22 Dec 1998 22:58:57 +0100 (CET)


Well.. here's what i hope is a working version of the
/proc/sys/kernel/corename code that I've been working on.
It should work for a.out and ELF, but the a.out version
is untested. (It does compile cleanly though).
The following codes are supported:

%p : pid
%c : command name (or first 15 chars of it anyway)
%G : gid
%U : uid
%P : parent pid
%r : parent gid
%n : nice (not sure if this is handled correctly)
%% : expands to % (if anyone wants a % in their corename
%y : tty

for example:

[root@lilith /root]# echo /tmp/core.%p.%c > /proc/sys/kernel/corename
[root@lilith /root]# ./0123456789
Dumping core as: /tmp/core.6025.0123456789
Segmentation fault (core dumped)
[root@lilith /root]# ls /tmp
core.6025.0123456789
[root@lilith /root]#

The "Dumping core as: /tmp/core.6025.012345678" is just a debugging
feature..

I'd be happy if a few people would help me try this out to see
that nothing goes wrong, any comments are appreciated.

Patch follows below.

Thanks..

-Simon Ekstrand

diff -u --recursive linux-2.1.131-clean/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- linux-2.1.131-clean/fs/binfmt_aout.c Tue Dec 22 18:30:09 1998
+++ linux/fs/binfmt_aout.c Tue Dec 22 22:41:01 1998
@@ -43,6 +43,12 @@
#endif
};

+#ifdef CONFIG_BINFMT_ELF
+extern char core_name[128];
+#else
+char core_name[128];
+#endif
+
static void set_brk(unsigned long start, unsigned long end)
{
start = PAGE_ALIGN(start);
@@ -85,7 +91,9 @@
struct file file;
mm_segment_t fs;
int has_dumped = 0;
- char corefile[6+sizeof(current->comm)];
+ char corefile[256];
+ char tmp_corefile[256];
+ int i,j,k,l;
unsigned long dump_start, dump_size;
struct user dump;
#if defined(__alpha__)
@@ -110,12 +118,68 @@
return 0;
fs = get_fs();
set_fs(KERNEL_DS);
- memcpy(corefile,"core.",5);
-#if 0
- memcpy(corefile+5,current->comm,sizeof(current->comm));
-#else
- corefile[4] = '\0';
-#endif
+
+ /* if core_name is empty, then don't coredump */
+ if(core_name[0]=='\0') {
+ /* we only open the [non]file to avoid a warning */
+ dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
+ goto end_coredump;
+ }
+ corefile[0]='\0';
+ i=0;
+ while((core_name[i]!='\0') && (i < 128) && (strlen(corefile) < 256)) {
+ j=0;
+ while((core_name[i]!='\0') && (core_name[i]!='%')) {
+ i++;
+ j++;
+ }
+ l=strlen(corefile);
+ for(k=0; k < j; k++) {
+ if(l+k < 255) corefile[l+k]=core_name[i-j+k];
+ }
+ corefile[l+j]='\0';
+ if((l+j < 256) && (core_name[i]=='%')) {
+ i++;
+ switch (core_name[i]) {
+/* pid */ case 'p' : sprintf(tmp_corefile,"%d",current->pid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* command name (short) */ case 'c' : if(strlen(current->comm) < (256-strlen(corefile))) strcat(corefile,current->comm);
+ break;
+/* gid */ case 'G' : sprintf(tmp_corefile,"%d",current->gid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* uid */ case 'U' : sprintf(tmp_corefile,"%d",current->uid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* parent pid */ case 'P' : sprintf(tmp_corefile,"%d",current->p_pptr->pid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* parent gid */ case 'r' : sprintf(tmp_corefile,"%d",current->p_pptr->gid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* nice value */ case 'n' : sprintf(tmp_corefile,"%ld",(current->priority-15));
+/* is this the correct way to do it? */ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* %% == % */ case '%' : if(strlen(corefile) < 256) strcat(corefile,"%");
+ break;
+/* tty */ case 'y' : tty_name(current->tty,tmp_corefile);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+ }
+ i++;
+ }
+ }
+
+
+ /* This shouldn't happen, it will only happen if core_name ONLY has
+ * one or more arguments that all expand to become more then 255 bytes.
+ * And because of that aren't included in corefile.. not likely.
+ */
+ if(strlen(corefile)==0) memcpy(corefile,"core",4);
+
+ printk("Dumping core as: %s\n",corefile);
+
dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
if (IS_ERR(dentry)) {
dentry = NULL;
diff -u --recursive linux-2.1.131-clean/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.1.131-clean/fs/binfmt_elf.c Tue Dec 22 18:30:02 1998
+++ linux/fs/binfmt_elf.c Tue Dec 22 22:25:14 1998
@@ -71,6 +71,8 @@
#endif
};

+char core_name[128]="core\0";
+
static void set_brk(unsigned long start, unsigned long end)
{
start = ELF_PAGEALIGN(start);
@@ -1051,7 +1053,9 @@
struct dentry *dentry;
struct inode *inode;
mm_segment_t fs;
- char corefile[6+sizeof(current->comm)];
+ char corefile[256];
+ char tmp_corefile[256];
+ int j,k,l;
int segs;
int i;
size_t size;
@@ -1091,6 +1095,7 @@

segs++;
}
+
#ifdef DEBUG
printk("elf_core_dump: %d segs taking %d bytes\n", segs, size);
#endif
@@ -1118,12 +1123,68 @@

fs = get_fs();
set_fs(KERNEL_DS);
- memcpy(corefile,"core.",5);
-#if 0
- memcpy(corefile+5,current->comm,sizeof(current->comm));
-#else
- corefile[4] = '\0';
-#endif
+
+ /* if core_name is empty, then don't coredump */
+ if(core_name[0]=='\0') {
+ /* we only open the [non]file to avoid a warning */
+ dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
+ goto end_coredump;
+ }
+ corefile[0]='\0';
+ i=0;
+ while((core_name[i]!='\0') && (i < 128) && (strlen(corefile) < 256)) {
+ j=0;
+ while((core_name[i]!='\0') && (core_name[i]!='%')) {
+ i++;
+ j++;
+ }
+ l=strlen(corefile);
+ for(k=0; k < j; k++) {
+ if(l+k < 255) corefile[l+k]=core_name[i-j+k];
+ }
+ corefile[l+j]='\0';
+ if((l+j < 256) && (core_name[i]=='%')) {
+ i++;
+ switch (core_name[i]) {
+/* pid */ case 'p' : sprintf(tmp_corefile,"%d",current->pid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* command name (short) */ case 'c' : if(strlen(current->comm) < (256-strlen(corefile))) strcat(corefile,current->comm);
+ break;
+/* gid */ case 'G' : sprintf(tmp_corefile,"%d",current->gid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* uid */ case 'U' : sprintf(tmp_corefile,"%d",current->uid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* parent pid */ case 'P' : sprintf(tmp_corefile,"%d",current->p_pptr->pid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* parent gid */ case 'r' : sprintf(tmp_corefile,"%d",current->p_pptr->gid);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* nice value */ case 'n' : sprintf(tmp_corefile,"%ld",(current->priority-15));
+/* is this the correct way to do it? */ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+/* %% == % */ case '%' : if(strlen(corefile) < 256) strcat(corefile,"%");
+ break;
+/* tty */ case 'y' : tty_name(current->tty,tmp_corefile);
+ if(strlen(tmp_corefile) < (256-strlen(corefile))) strcat(corefile,tmp_corefile);
+ break;
+ }
+ i++;
+ }
+ }
+
+
+ /* This shouldn't happen, it will only happen if core_name ONLY has
+ * one or more arguments that all expand to become more then 255 bytes.
+ * And because of that aren't included in corefile.. not likely.
+ */
+ if(strlen(corefile)==0) memcpy(corefile,"core",4);
+
+ printk("Dumping core as: %s\n",corefile);
+
dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
if (IS_ERR(dentry)) {
dentry = NULL;
diff -u --recursive linux-2.1.131-clean/include/linux/sysctl.h linux/include/linux/sysctl.h
--- linux-2.1.131-clean/include/linux/sysctl.h Tue Dec 22 18:30:09 1998
+++ linux/include/linux/sysctl.h Tue Dec 22 22:25:14 1998
@@ -89,6 +89,7 @@
KERN_SG_BIG_BUFF=29,
KERN_ACCT=30, /* BSD process accounting parameters */
KERN_PPC_L2CR=31, /* l2cr register on PPC */
+ KERN_CORENAME=32 /* for the coredump code */
};


diff -u --recursive linux-2.1.131-clean/kernel/sysctl.c linux/kernel/sysctl.c
--- linux-2.1.131-clean/kernel/sysctl.c Tue Dec 22 18:31:17 1998
+++ linux/kernel/sysctl.c Tue Dec 22 22:25:14 1998
@@ -56,6 +56,8 @@
extern int acct_parm[];
#endif

+extern char core_name[128];
+
extern int pgt_cache_water[];

static int parse_table(int *, int, void *, size_t *, void *, size_t,
@@ -195,6 +197,9 @@
{KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
0644, NULL, &proc_dointvec},
#endif
+ {KERN_CORENAME, "corename", &core_name, 128,
+ 0644, NULL, &proc_dostring, &sysctl_string },
+
{0}
};

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/