1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
/* The kernel call implemented in this file:
* m_type: SYS_GETINFO
*
* The parameters for this kernel call are:
* m_lsys_krn_sys_getinfo.request (what info to get)
* m_lsys_krn_sys_getinfo.val_ptr (where to put it)
* m_lsys_krn_sys_getinfo.val_len (maximum length expected, optional)
* m_lsys_krn_sys_getinfo.val_ptr2 (second, optional pointer)
* m_lsys_krn_sys_getinfo.val_len2_e (second length or process nr)
*
* Upon return of the GETWHOAMI request the following parameters are used:
* m_krn_lsys_sys_getwhoami.endpt (the caller endpoint)
* m_krn_lsys_sys_getwhoami.privflags (the caller priviledes)
* m_krn_lsys_sys_getwhoami.initflags (the caller initflags)
* m_krn_lsys_sys_getwhoami.name (the caller process name)
*
*/
#include <string.h>
#include "kernel/system.h"
#if USE_GETINFO
#include <minix/u64.h>
#include <sys/resource.h>
/*===========================================================================*
* update_idle_time *
*===========================================================================*/
static void update_idle_time(void)
{
int i;
struct proc * idl = proc_addr(IDLE);
idl->p_cycles = make64(0, 0);
for (i = 0; i < CONFIG_MAX_CPUS ; i++) {
idl->p_cycles += get_cpu_var(i, idle_proc).p_cycles;
}
}
/*===========================================================================*
* do_getinfo *
*===========================================================================*/
int do_getinfo(struct proc * caller, message * m_ptr)
{
/* Request system information to be copied to caller's address space. This
* call simply copies entire data structures to the caller.
*/
size_t length;
vir_bytes src_vir;
int nr_e, nr, r;
int wipe_rnd_bin = -1;
struct proc *p;
struct rusage r_usage;
/* Set source address and length based on request type. */
switch (m_ptr->m_lsys_krn_sys_getinfo.request) {
case GET_MACHINE: {
length = sizeof(struct machine);
src_vir = (vir_bytes) &machine;
break;
}
case GET_KINFO: {
length = sizeof(struct kinfo);
src_vir = (vir_bytes) &kinfo;
break;
}
case GET_LOADINFO: {
length = sizeof(struct loadinfo);
src_vir = (vir_bytes) &kloadinfo;
break;
}
case GET_CPUINFO: {
length = sizeof(cpu_info);
src_vir = (vir_bytes) &cpu_info;
break;
}
case GET_HZ: {
length = sizeof(system_hz);
src_vir = (vir_bytes) &system_hz;
break;
}
case GET_IMAGE: {
length = sizeof(struct boot_image) * NR_BOOT_PROCS;
src_vir = (vir_bytes) image;
break;
}
case GET_IRQHOOKS: {
length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
src_vir = (vir_bytes) irq_hooks;
break;
}
case GET_PROCTAB: {
update_idle_time();
length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
src_vir = (vir_bytes) proc;
break;
}
case GET_PRIVTAB: {
length = sizeof(struct priv) * (NR_SYS_PROCS);
src_vir = (vir_bytes) priv;
break;
}
case GET_PROC: {
nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
length = sizeof(struct proc);
src_vir = (vir_bytes) proc_addr(nr);
break;
}
case GET_PRIV: {
nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
length = sizeof(struct priv);
src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
break;
}
case GET_REGS: {
nr_e = (m_ptr->m_lsys_krn_sys_getinfo.val_len2_e == SELF) ?
caller->p_endpoint : m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
p = proc_addr(nr);
length = sizeof(p->p_reg);
src_vir = (vir_bytes) &p->p_reg;
break;
}
case GET_WHOAMI: {
int len;
m_ptr->m_krn_lsys_sys_getwhoami.endpt = caller->p_endpoint;
len = MIN(sizeof(m_ptr->m_krn_lsys_sys_getwhoami.name),
sizeof(caller->p_name))-1;
strncpy(m_ptr->m_krn_lsys_sys_getwhoami.name, caller->p_name, len);
m_ptr->m_krn_lsys_sys_getwhoami.name[len] = '\0';
m_ptr->m_krn_lsys_sys_getwhoami.privflags = priv(caller)->s_flags;
m_ptr->m_krn_lsys_sys_getwhoami.initflags = priv(caller)->s_init_flags;
return OK;
}
case GET_MONPARAMS: {
src_vir = (vir_bytes) kinfo.param_buf;
length = sizeof(kinfo.param_buf);
break;
}
case GET_RANDOMNESS: {
static struct k_randomness copy; /* copy to keep counters */
int i;
copy = krandom;
for (i= 0; i<RANDOM_SOURCES; i++) {
krandom.bin[i].r_size = 0; /* invalidate random data */
krandom.bin[i].r_next = 0;
}
length = sizeof(copy);
src_vir = (vir_bytes) ©
break;
}
case GET_RANDOMNESS_BIN: {
int bin = m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
if(bin < 0 || bin >= RANDOM_SOURCES) {
printf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin);
return EINVAL;
}
if(krandom.bin[bin].r_size < RANDOM_ELEMENTS)
return ENOENT;
length = sizeof(krandom.bin[bin]);
src_vir = (vir_bytes) &krandom.bin[bin];
wipe_rnd_bin = bin;
break;
}
case GET_IRQACTIDS: {
length = sizeof(irq_actids);
src_vir = (vir_bytes) irq_actids;
break;
}
case GET_IDLETSC: {
struct proc * idl;
update_idle_time();
idl = proc_addr(IDLE);
length = sizeof(idl->p_cycles);
src_vir = (vir_bytes) &idl->p_cycles;
break;
}
case GET_CPUTICKS: {
uint64_t ticks[MINIX_CPUSTATES];
unsigned int cpu;
cpu = (unsigned int)m_ptr->m_lsys_krn_sys_getinfo.val_len2_e;
if (cpu >= CONFIG_MAX_CPUS)
return EINVAL;
get_cpu_ticks(cpu, ticks);
length = sizeof(ticks);
src_vir = (vir_bytes)ticks;
break;
}
default:
printf("do_getinfo: invalid request %d\n",
m_ptr->m_lsys_krn_sys_getinfo.request);
return(EINVAL);
}
/* Try to make the actual copy for the requested data. */
if (m_ptr->m_lsys_krn_sys_getinfo.val_len > 0 &&
length > m_ptr->m_lsys_krn_sys_getinfo.val_len)
return (E2BIG);
r = data_copy_vmcheck(caller, KERNEL, src_vir, caller->p_endpoint,
m_ptr->m_lsys_krn_sys_getinfo.val_ptr, length);
if(r != OK) return r;
if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) {
krandom.bin[wipe_rnd_bin].r_size = 0;
krandom.bin[wipe_rnd_bin].r_next = 0;
}
return(OK);
}
#endif /* USE_GETINFO */
|