1 /*
2  *  linux/fs/proc/array.c
3  *
4  *  Copyright (C) 1992  by Linus Torvalds
5  *  based on ideas by Darren Senn
6  *
7  * Fixes:
8  * Michael. K. Johnson: stat,statm extensions.
9  *                      <johnsonm@stolaf.edu>
10  *
11  * Pauline Middelink :  Made cmdline,envline only break at '\0's, to
12  *                      make sure SET_PROCTITLE works. Also removed
13  *                      bad '!' which forced address recalculation for
14  *                      EVERY character on the current page.
15  *                      <middelin@polyware.iaf.nl>
16  *
17  * Danny ter Haar    :	added cpuinfo
18  *			<dth@cistron.nl>
19  *
20  * Alessandro Rubini :  profile extension.
21  *                      <rubini@ipvvis.unipv.it>
22  *
23  * Jeff Tranter      :  added BogoMips field to cpuinfo
24  *                      <Jeff_Tranter@Mitel.COM>
25  *
26  * Bruno Haible      :  remove 4K limit for the maps file
27  *			<haible@ma2s2.mathematik.uni-karlsruhe.de>
28  *
29  * Yves Arrouye      :  remove removal of trailing spaces in get_array.
30  *			<Yves.Arrouye@marin.fdn.fr>
31  *
32  * Jerome Forissier  :  added per-CPU time information to /proc/stat
33  *                      and /proc/<pid>/cpu extension
34  *                      <forissier@isia.cma.fr>
35  *			- Incorporation and non-SMP safe operation
36  *			of forissier patch in 2.1.78 by
37  *			Hans Marcus <crowbar@concepts.nl>
38  *
39  * aeb@cwi.nl        :  /proc/partitions
40  *
41  *
42  * Alan Cox	     :  security fixes.
43  *			<Alan.Cox@linux.org>
44  *
45  * Al Viro           :  safe handling of mm_struct
46  *
47  * Gerhard Wichert   :  added BIGMEM support
48  * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
49  *
50  * Al Viro & Jeff Garzik :  moved most of the thing into base.c and
51  *			 :  proc_misc.c. The rest may eventually go into
52  *			 :  base.c too.
53  */
54 
55 #include <linux/config.h>
56 #include <linux/types.h>
57 #include <linux/errno.h>
58 #include <linux/sched.h>
59 #include <linux/kernel.h>
60 #include <linux/kernel_stat.h>
61 #include <linux/tty.h>
62 #include <linux/string.h>
63 #include <linux/mman.h>
64 #include <linux/proc_fs.h>
65 #include <linux/ioport.h>
66 #include <linux/mm.h>
67 #include <linux/pagemap.h>
68 #include <linux/swap.h>
69 #include <linux/slab.h>
70 #include <linux/smp.h>
71 #include <linux/signal.h>
72 #include <linux/highmem.h>
73 #include <linux/seq_file.h>
74 
75 #include <asm/uaccess.h>
76 #include <asm/pgtable.h>
77 #include <asm/io.h>
78 #include <asm/processor.h>
79 
80 /* Gcc optimizes away "strlen(x)" for constant x */
81 #define ADDBUF(buffer, string) \
82 do { memcpy(buffer, string, strlen(string)); \
83      buffer += strlen(string); } while (0)
84 
task_name(struct task_struct * p,char * buf)85 static inline char * task_name(struct task_struct *p, char * buf)
86 {
87 	int i;
88 	char * name;
89 	char tcomm[sizeof(p->comm)];
90 
91 	get_task_comm(tcomm, p);
92 
93 	ADDBUF(buf, "Name:\t");
94 	name = tcomm;
95 	i = sizeof(tcomm);
96 	do {
97 		unsigned char c = *name;
98 		name++;
99 		i--;
100 		*buf = c;
101 		if (!c)
102 			break;
103 		if (c == '\\') {
104 			buf[1] = c;
105 			buf += 2;
106 			continue;
107 		}
108 		if (c == '\n') {
109 			buf[0] = '\\';
110 			buf[1] = 'n';
111 			buf += 2;
112 			continue;
113 		}
114 		buf++;
115 	} while (i);
116 	*buf = '\n';
117 	return buf+1;
118 }
119 
120 /*
121  * The task state array is a strange "bitmap" of
122  * reasons to sleep. Thus "running" is zero, and
123  * you can test for combinations of others with
124  * simple bit tests.
125  */
126 static const char *task_state_array[] = {
127 	"R (running)",		/*  0 */
128 	"S (sleeping)",		/*  1 */
129 	"D (disk sleep)",	/*  2 */
130 	"Z (zombie)",		/*  4 */
131 	"T (stopped)",		/*  8 */
132 	"W (paging)"		/* 16 */
133 };
134 
get_task_state(struct task_struct * tsk)135 static inline const char * get_task_state(struct task_struct *tsk)
136 {
137 	unsigned int state = tsk->state & (TASK_RUNNING |
138 					   TASK_INTERRUPTIBLE |
139 					   TASK_UNINTERRUPTIBLE |
140 					   TASK_ZOMBIE |
141 					   TASK_STOPPED);
142 	const char **p = &task_state_array[0];
143 
144 	while (state) {
145 		p++;
146 		state >>= 1;
147 	}
148 	return *p;
149 }
150 
task_state(struct task_struct * p,char * buffer)151 static inline char * task_state(struct task_struct *p, char *buffer)
152 {
153 	int g;
154 
155 	read_lock(&tasklist_lock);
156 	buffer += sprintf(buffer,
157 		"State:\t%s\n"
158 		"Tgid:\t%d\n"
159 		"Pid:\t%d\n"
160 		"PPid:\t%d\n"
161 		"TracerPid:\t%d\n"
162 		"Uid:\t%d\t%d\t%d\t%d\n"
163 		"Gid:\t%d\t%d\t%d\t%d\n",
164 		get_task_state(p), p->tgid,
165 		p->pid, p->pid ? p->p_opptr->pid : 0, 0,
166 		p->uid, p->euid, p->suid, p->fsuid,
167 		p->gid, p->egid, p->sgid, p->fsgid);
168 	read_unlock(&tasklist_lock);
169 	task_lock(p);
170 	buffer += sprintf(buffer,
171 		"FDSize:\t%d\n"
172 		"Groups:\t",
173 		p->files ? p->files->max_fds : 0);
174 	task_unlock(p);
175 
176 	for (g = 0; g < p->ngroups; g++)
177 		buffer += sprintf(buffer, "%d ", p->groups[g]);
178 
179 	buffer += sprintf(buffer, "\n");
180 	return buffer;
181 }
182 
task_mem(struct mm_struct * mm,char * buffer)183 static inline char * task_mem(struct mm_struct *mm, char *buffer)
184 {
185 	struct vm_area_struct * vma;
186 	unsigned long data = 0, stack = 0;
187 	unsigned long exec = 0, lib = 0;
188 
189 	down_read(&mm->mmap_sem);
190 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
191 		unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
192 		if (!vma->vm_file) {
193 			data += len;
194 			if (vma->vm_flags & VM_GROWSDOWN)
195 				stack += len;
196 			continue;
197 		}
198 		if (vma->vm_flags & VM_WRITE)
199 			continue;
200 		if (vma->vm_flags & VM_EXEC) {
201 			exec += len;
202 			if (vma->vm_flags & VM_EXECUTABLE)
203 				continue;
204 			lib += len;
205 		}
206 	}
207 	buffer += sprintf(buffer,
208 		"VmSize:\t%8lu kB\n"
209 		"VmLck:\t%8lu kB\n"
210 		"VmRSS:\t%8lu kB\n"
211 		"VmData:\t%8lu kB\n"
212 		"VmStk:\t%8lu kB\n"
213 		"VmExe:\t%8lu kB\n"
214 		"VmLib:\t%8lu kB\n",
215 		mm->total_vm << (PAGE_SHIFT-10),
216 		mm->locked_vm << (PAGE_SHIFT-10),
217 		mm->rss << (PAGE_SHIFT-10),
218 		data - stack, stack,
219 		exec - lib, lib);
220 	up_read(&mm->mmap_sem);
221 	return buffer;
222 }
223 
collect_sigign_sigcatch(struct task_struct * p,sigset_t * ign,sigset_t * catch)224 static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
225 				    sigset_t *catch)
226 {
227 	struct k_sigaction *k;
228 	int i;
229 
230 	sigemptyset(ign);
231 	sigemptyset(catch);
232 
233 	spin_lock_irq(&p->sigmask_lock);
234 
235 	if (p->sig) {
236 		k = p->sig->action;
237 		for (i = 1; i <= _NSIG; ++i, ++k) {
238 			if (k->sa.sa_handler == SIG_IGN)
239 				sigaddset(ign, i);
240 			else if (k->sa.sa_handler != SIG_DFL)
241 				sigaddset(catch, i);
242 		}
243 	}
244 	spin_unlock_irq(&p->sigmask_lock);
245 }
246 
task_sig(struct task_struct * p,char * buffer)247 static inline char * task_sig(struct task_struct *p, char *buffer)
248 {
249 	sigset_t ign, catch;
250 
251 	buffer += sprintf(buffer, "SigPnd:\t");
252 	buffer = render_sigset_t(&p->pending.signal, buffer);
253 	*buffer++ = '\n';
254 	buffer += sprintf(buffer, "SigBlk:\t");
255 	buffer = render_sigset_t(&p->blocked, buffer);
256 	*buffer++ = '\n';
257 
258 	collect_sigign_sigcatch(p, &ign, &catch);
259 	buffer += sprintf(buffer, "SigIgn:\t");
260 	buffer = render_sigset_t(&ign, buffer);
261 	*buffer++ = '\n';
262 	buffer += sprintf(buffer, "SigCgt:\t"); /* Linux 2.0 uses "SigCgt" */
263 	buffer = render_sigset_t(&catch, buffer);
264 	*buffer++ = '\n';
265 
266 	return buffer;
267 }
268 
task_cap(struct task_struct * p,char * buffer)269 static inline char *task_cap(struct task_struct *p, char *buffer)
270 {
271     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
272 			    "CapPrm:\t%016x\n"
273 			    "CapEff:\t%016x\n",
274 			    cap_t(p->cap_inheritable),
275 			    cap_t(p->cap_permitted),
276 			    cap_t(p->cap_effective));
277 }
278 
279 
proc_pid_status(struct task_struct * task,char * buffer)280 int proc_pid_status(struct task_struct *task, char * buffer)
281 {
282 	char * orig = buffer;
283 	struct mm_struct *mm;
284 
285 	buffer = task_name(task, buffer);
286 	buffer = task_state(task, buffer);
287 	task_lock(task);
288 	mm = task->mm;
289 	if(mm)
290 		atomic_inc(&mm->mm_users);
291 	task_unlock(task);
292 	if (mm) {
293 		buffer = task_mem(mm, buffer);
294 		mmput(mm);
295 	}
296 	buffer = task_sig(task, buffer);
297 	buffer = task_cap(task, buffer);
298 #if defined(CONFIG_ARCH_S390)
299 	buffer = task_show_regs(task, buffer);
300 #endif
301 	return buffer - orig;
302 }
303 
proc_pid_stat(struct task_struct * task,char * buffer)304 int proc_pid_stat(struct task_struct *task, char * buffer)
305 {
306 	unsigned long vsize, eip, esp, wchan = ~0UL;
307 	long priority, nice;
308 	int tty_pgrp = -1, tty_nr = 0;
309 	sigset_t sigign, sigcatch;
310 	char state;
311 	int res;
312 	pid_t ppid;
313 	int permitted;
314 	struct mm_struct *mm;
315 	char tcomm[sizeof(task->comm)];
316 
317 	state = *get_task_state(task);
318 	vsize = eip = esp = 0;
319 	permitted = capable(CAP_SYS_PTRACE) ||
320 		(current->uid == task->euid && current->uid == task->suid &&
321 		 current->uid == task->uid  && current->gid == task->egid &&
322 		 current->gid == task->sgid && current->gid == task->gid);
323 	task_lock(task);
324 	mm = task->mm;
325 	if(mm)
326 		atomic_inc(&mm->mm_users);
327 	if (task->tty) {
328 		tty_pgrp = task->tty->pgrp;
329 		tty_nr = kdev_t_to_nr(task->tty->device);
330 	}
331 	task_unlock(task);
332 	if (mm) {
333 		struct vm_area_struct *vma;
334 		down_read(&mm->mmap_sem);
335 		vma = mm->mmap;
336 		while (vma) {
337 			vsize += vma->vm_end - vma->vm_start;
338 			vma = vma->vm_next;
339 		}
340 		if (permitted) {
341 			eip = KSTK_EIP(task);
342 			esp = KSTK_ESP(task);
343 		}
344 		up_read(&mm->mmap_sem);
345 	}
346 
347 	get_task_comm(tcomm, task);
348 
349 	if (permitted)
350 		wchan = get_wchan(task);
351 
352 	collect_sigign_sigcatch(task, &sigign, &sigcatch);
353 
354 	/* scale priority and nice values from timeslices to -20..20 */
355 	/* to make it look like a "normal" Unix priority/nice value  */
356 	priority = task->counter;
357 	priority = 20 - (priority * 10 + DEF_COUNTER / 2) / DEF_COUNTER;
358 	nice = task->nice;
359 
360 	read_lock(&tasklist_lock);
361 	ppid = task->pid ? task->p_opptr->pid : 0;
362 	read_unlock(&tasklist_lock);
363 	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
364 %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
365 %lu %lu %lu %lu %lu %lu %lu %lu %d %d\n",
366 		task->pid,
367 		tcomm,
368 		state,
369 		ppid,
370 		task->pgrp,
371 		task->session,
372 	        tty_nr,
373 		tty_pgrp,
374 		task->flags,
375 		task->min_flt,
376 		task->cmin_flt,
377 		task->maj_flt,
378 		task->cmaj_flt,
379 		task->times.tms_utime,
380 		task->times.tms_stime,
381 		task->times.tms_cutime,
382 		task->times.tms_cstime,
383 		priority,
384 		nice,
385 		0UL /* removed */,
386 		task->it_real_value,
387 		task->start_time,
388 		vsize,
389 		mm ? mm->rss : 0, /* you might want to shift this left 3 */
390 		task->rlim[RLIMIT_RSS].rlim_cur,
391 		mm ? mm->start_code : 0,
392 		mm ? mm->end_code : 0,
393 		(permitted && mm) ? mm->start_stack : 0,
394 		esp,
395 		eip,
396 		/* The signal information here is obsolete.
397 		 * It must be decimal for Linux 2.0 compatibility.
398 		 * Use /proc/#/status for real-time signals.
399 		 */
400 		task->pending.signal.sig[0] & 0x7fffffffUL,
401 		task->blocked.sig[0] & 0x7fffffffUL,
402 		sigign      .sig[0] & 0x7fffffffUL,
403 		sigcatch    .sig[0] & 0x7fffffffUL,
404 		wchan,
405 		task->nswap,
406 		task->cnswap,
407 		task->exit_signal,
408 		task->processor);
409 	if(mm)
410 		mmput(mm);
411 	return res;
412 }
413 
statm_pte_range(pmd_t * pmd,unsigned long address,unsigned long size,int * pages,int * shared,int * dirty,int * total)414 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
415 	int * pages, int * shared, int * dirty, int * total)
416 {
417 	pte_t * pte;
418 	unsigned long end;
419 
420 	if (pmd_none(*pmd))
421 		return;
422 	if (pmd_bad(*pmd)) {
423 		pmd_ERROR(*pmd);
424 		pmd_clear(pmd);
425 		return;
426 	}
427 	pte = pte_offset(pmd, address);
428 	address &= ~PMD_MASK;
429 	end = address + size;
430 	if (end > PMD_SIZE)
431 		end = PMD_SIZE;
432 	do {
433 		pte_t page = *pte;
434 		struct page *ptpage;
435 
436 		address += PAGE_SIZE;
437 		pte++;
438 		if (pte_none(page))
439 			continue;
440 		++*total;
441 		if (!pte_present(page))
442 			continue;
443 		ptpage = pte_page(page);
444 		if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage))
445 			continue;
446 		++*pages;
447 		if (pte_dirty(page))
448 			++*dirty;
449 		if (page_count(pte_page(page)) > 1)
450 			++*shared;
451 	} while (address < end);
452 }
453 
statm_pmd_range(pgd_t * pgd,unsigned long address,unsigned long size,int * pages,int * shared,int * dirty,int * total)454 static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
455 	int * pages, int * shared, int * dirty, int * total)
456 {
457 	pmd_t * pmd;
458 	unsigned long end;
459 
460 	if (pgd_none(*pgd))
461 		return;
462 	if (pgd_bad(*pgd)) {
463 		pgd_ERROR(*pgd);
464 		pgd_clear(pgd);
465 		return;
466 	}
467 	pmd = pmd_offset(pgd, address);
468 	address &= ~PGDIR_MASK;
469 	end = address + size;
470 	if (end > PGDIR_SIZE)
471 		end = PGDIR_SIZE;
472 	do {
473 		statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
474 		address = (address + PMD_SIZE) & PMD_MASK;
475 		pmd++;
476 	} while (address < end);
477 }
478 
statm_pgd_range(pgd_t * pgd,unsigned long address,unsigned long end,int * pages,int * shared,int * dirty,int * total)479 static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
480 	int * pages, int * shared, int * dirty, int * total)
481 {
482 	while (address < end) {
483 		statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
484 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
485 		pgd++;
486 	}
487 }
488 
proc_pid_statm(struct task_struct * task,char * buffer)489 int proc_pid_statm(struct task_struct *task, char * buffer)
490 {
491 	struct mm_struct *mm;
492 	int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
493 
494 	task_lock(task);
495 	mm = task->mm;
496 	if(mm)
497 		atomic_inc(&mm->mm_users);
498 	task_unlock(task);
499 	if (mm) {
500 		struct vm_area_struct * vma;
501 		down_read(&mm->mmap_sem);
502 		vma = mm->mmap;
503 		while (vma) {
504 			pgd_t *pgd = pgd_offset(mm, vma->vm_start);
505 			int pages = 0, shared = 0, dirty = 0, total = 0;
506 
507 			statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
508 			resident += pages;
509 			share += shared;
510 			dt += dirty;
511 			size += total;
512 			if (vma->vm_flags & VM_EXECUTABLE)
513 				trs += pages;	/* text */
514 			else if (vma->vm_flags & VM_GROWSDOWN)
515 				drs += pages;	/* stack */
516 			else if (vma->vm_end > 0x60000000)
517 				lrs += pages;	/* library */
518 			else
519 				drs += pages;
520 			vma = vma->vm_next;
521 		}
522 		up_read(&mm->mmap_sem);
523 		mmput(mm);
524 	}
525 	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
526 		       size, resident, share, trs, lrs, drs, dt);
527 }
528 
show_map(struct seq_file * m,void * v)529 static int show_map(struct seq_file *m, void *v)
530 {
531 	struct vm_area_struct *map = v;
532 	struct file *file = map->vm_file;
533 	int flags = map->vm_flags;
534 	unsigned long ino = 0;
535 	dev_t dev = 0;
536 	int len;
537 
538 	if (file) {
539 		struct inode *inode = map->vm_file->f_dentry->d_inode;
540 		dev = kdev_t_to_nr(inode->i_sb->s_dev);
541 		ino = inode->i_ino;
542 	}
543 
544 	seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
545 			map->vm_start,
546 			map->vm_end,
547 			flags & VM_READ ? 'r' : '-',
548 			flags & VM_WRITE ? 'w' : '-',
549 			flags & VM_EXEC ? 'x' : '-',
550 			flags & VM_MAYSHARE ? 's' : 'p',
551 			map->vm_pgoff << PAGE_SHIFT,
552 			MAJOR(dev), MINOR(dev), ino, &len);
553 
554 	if (map->vm_file) {
555 		len = 25 + sizeof(void*) * 6 - len;
556 		if (len < 1)
557 			len = 1;
558 		seq_printf(m, "%*c", len, ' ');
559 		seq_path(m, file->f_vfsmnt, file->f_dentry, "");
560 	}
561 	seq_putc(m, '\n');
562 	return 0;
563 }
564 
m_start(struct seq_file * m,loff_t * pos)565 static void *m_start(struct seq_file *m, loff_t *pos)
566 {
567 	struct task_struct *task = m->private;
568 	struct mm_struct *mm;
569 	struct vm_area_struct * map;
570 	loff_t l = *pos;
571 
572 	task_lock(task);
573 	mm = task->mm;
574 	if (mm && mm != current->mm &&
575 	    !capable(CAP_SYS_PTRACE) &&
576 	    ((current->uid != task->euid) || (current->uid != task->suid) ||
577 	     (current->uid != task->uid)  || (current->gid != task->egid) ||
578 	     (current->gid != task->sgid) || (current->gid != task->gid)))
579 		mm = NULL;
580 	if (mm)
581 		atomic_inc(&mm->mm_users);
582 	task_unlock(task);
583 
584 	if (!mm)
585 		return NULL;
586 
587 	down_read(&mm->mmap_sem);
588 	map = mm->mmap;
589 	while (l-- && map)
590 		map = map->vm_next;
591 	if (!map) {
592 		up_read(&mm->mmap_sem);
593 		mmput(mm);
594 	}
595 	return map;
596 }
597 
m_stop(struct seq_file * m,void * v)598 static void m_stop(struct seq_file *m, void *v)
599 {
600 	struct vm_area_struct *map = v;
601 	if (map) {
602 		struct mm_struct *mm = map->vm_mm;
603 		up_read(&mm->mmap_sem);
604 		mmput(mm);
605 	}
606 }
607 
m_next(struct seq_file * m,void * v,loff_t * pos)608 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
609 {
610 	struct vm_area_struct *map = v;
611 	(*pos)++;
612 	if (map->vm_next)
613 		return map->vm_next;
614 	m_stop(m, v);
615 	return NULL;
616 }
617 
618 struct seq_operations proc_pid_maps_op = {
619 	.start	= m_start,
620 	.next	= m_next,
621 	.stop	= m_stop,
622 	.show	= show_map
623 };
624 
625 #ifdef CONFIG_SMP
proc_pid_cpu(struct task_struct * task,char * buffer)626 int proc_pid_cpu(struct task_struct *task, char * buffer)
627 {
628 	int i, len;
629 
630 	len = sprintf(buffer,
631 		"cpu  %lu %lu\n",
632 		task->times.tms_utime,
633 		task->times.tms_stime);
634 
635 	for (i = 0 ; i < smp_num_cpus; i++)
636 		len += sprintf(buffer + len, "cpu%d %lu %lu\n",
637 			i,
638 			task->per_cpu_utime[cpu_logical_map(i)],
639 			task->per_cpu_stime[cpu_logical_map(i)]);
640 
641 	return len;
642 }
643 #endif
644