ia64/xen-unstable

view tools/security/labelfuncs.sh @ 7238:971e7c7411b3

Raise an exception if an error appears on the pipes to our children, and make
sure that the child's pipes are closed even under that exception. Move the
handling of POLLHUP to the end of the loop, so that we guarantee to read any
remaining data from the child if POLLHUP and POLLIN appear at the same time.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Thu Oct 06 10:13:11 2005 +0100 (2005-10-06)
parents 06d84bf87159
children 8aac8746047b
line source
1 # *
2 # * labelfuncs.sh
3 # *
4 # * Copyright (C) 2005 IBM Corporation
5 # *
6 # * Authors:
7 # * Stefan Berger <stefanb@us.ibm.com>
8 # *
9 # * This program is free software; you can redistribute it and/or
10 # * modify it under the terms of the GNU General Public License as
11 # * published by the Free Software Foundation, version 2 of the
12 # * License.
13 # *
14 # *
15 # * A collection of functions to handle polcies, mapfiles,
16 # * and ssidrefs.
17 #
20 # Find the mapfile given a policy nmame
21 # Parameters:
22 # 1st : the name of the policy whose map file is to be found, i.e.,
23 # chwall
24 # Results:
25 # The variable mapfile will hold the realtive path to the mapfile
26 # for the given policy.
27 # In case the mapfile could be found, the functions returns a '1',
28 # a '0' otherwise.
29 findMapFile ()
30 {
31 mapfile="./$1.map"
32 if [ -r "$mapfile" ]; then
33 return 1
34 fi
36 mapfile="./policies/$1/$1.map"
37 if [ -r "$mapfile" ]; then
38 return 1
39 fi
41 return 0
42 }
45 # Determine the name of the primary policy
46 # Parameters
47 # 1st : the path to the mapfile; the path may be relative
48 # to the current directory
49 # Results
50 # The variable primary will hold the name of the primary policy
51 getPrimaryPolicy ()
52 {
53 mapfile=$1
54 primary=`cat $mapfile | \
55 awk ' \
56 { \
57 if ( $1 == "PRIMARY" ) { \
58 res=$2; \
59 } \
60 } END { \
61 print res; \
62 } '`
63 }
66 # Determine the name of the secondary policy
67 # Parameters
68 # 1st : the path to the mapfile; the path may be relative
69 # to the current directory
70 # Results
71 # The variable secondary will hold the name of the secondary policy
72 getSecondaryPolicy ()
73 {
74 mapfile=$1
75 secondary=`cat $mapfile | \
76 awk ' \
77 { \
78 if ( $1 == "SECONDARY" ) { \
79 res=$2; \
80 } \
81 } END { \
82 print res; \
83 } '`
84 }
87 #Return where the grub.conf file is.
88 #I only know of one place it can be.
89 findGrubConf()
90 {
91 grubconf="/boot/grub/grub.conf"
92 if [ -w $grubconf ]; then
93 return 1
94 fi
95 if [ -r $grubconf ]; then
96 return 2
97 fi
98 return 0
99 }
102 # This function sets the global variable 'linux'
103 # to the name and version of the Linux kernel that was compiled
104 # for domain 0.
105 # If this variable could not be found, the variable 'linux'
106 # will hold a pattern
107 # Parameters:
108 # 1st: the path to reach the root directory of the XEN build tree
109 # where linux-*-xen0 is located at
110 # Results:
111 # The variable linux holds then name and version of the compiled
112 # kernel, i.e., 'vmlinuz-2.6.12-xen0'
113 getLinuxVersion ()
114 {
115 path=$1
116 linux=""
117 for f in $path/linux-*-xen0 ; do
118 versionfile=$f/include/linux/version.h
119 if [ -r $versionfile ]; then
120 lnx=`cat $versionfile | \
121 grep UTS_RELEASE | \
122 awk '{ \
123 len=length($3); \
124 print substr($3,2,len-2) }'`
125 fi
126 if [ "$lnx" != "" ]; then
127 linux="[./0-9a-zA-z]*$lnx"
128 return;
129 fi
130 done
132 #Last resort.
133 linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$"
134 }
137 # Find out with which policy the hypervisor was booted with.
138 # Parameters
139 # 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf
140 #
141 findPolicyInGrub ()
142 {
143 grubconf=$1
144 linux=`uname -r`
145 policy=`cat $grubconf | \
146 awk -vlinux=$linux '{ \
147 if ( $1 == "title" ) { \
148 kernelfound = 0; \
149 policymaycome = 0; \
150 } \
151 else if ( $1 == "kernel" ) { \
152 if ( match($2,"xen.gz$") ) { \
153 pathlen=RSTART; \
154 kernelfound = 1; \
155 } \
156 } \
157 else if ( $1 == "module" && \
158 kernelfound == 1 && \
159 match($2,linux) ) { \
160 policymaycome = 1; \
161 } \
162 else if ( $1 == "module" && \
163 kernelfound == 1 && \
164 policymaycome == 1 && \
165 match($2,"[0-9a-zA-Z_]*.bin$") ) { \
166 policymaycome = 0; \
167 kernelfound = 0; \
168 polname = substr($2,pathlen); \
169 len=length(polname); \
170 polname = substr(polname,0,len-4); \
171 } \
172 } END { \
173 print polname \
174 }'`
175 }
178 # Get the SSID of a domain
179 # Parameters:
180 # 1st : domain ID, i.e. '1'
181 # Results
182 # If the ssid could be found, the variable 'ssid' will hold
183 # the currently used ssid in the hex format, i.e., '0x00010001'.
184 # The funtion returns '1' on success, '0' on failure
185 getSSIDUsingSecpolTool ()
186 {
187 domid=$1
188 export PATH=$PATH:.
189 ssid=`secpol_tool getssid -d $domid -f | \
190 grep -E "SSID:" | \
191 awk '{ print $4 }'`
193 if [ "$ssid" != "" ]; then
194 return 1
195 fi
196 return 0
197 }
200 # Break the ssid identifier into its high and low values,
201 # which are equal to the secondary and primary policy references.
202 # Parameters:
203 # 1st: ssid to break into high and low value, i.e., '0x00010002'
204 # Results:
205 # The variable ssidlo_int and ssidhi_int will hold the low and
206 # high ssid values as integers.
207 getSSIDLOHI ()
208 {
209 ssid=$1
210 ssidlo_int=`echo $ssid | awk \
211 '{ \
212 len=length($0); \
213 beg=substr($0,1,2); \
214 if ( beg == "0x" ) { \
215 dig = len - 2; \
216 if (dig <= 0) { \
217 exit; \
218 } \
219 if (dig > 4) { \
220 dig=4; \
221 } \
222 lo=sprintf("0x%s",substr($0,len-dig+1,dig)); \
223 print strtonum(lo);\
224 } else { \
225 lo=strtonum($0); \
226 if (lo < 65536) { \
227 print lo; \
228 } else { \
229 hi=lo; \
230 hi2= (hi / 65536);\
231 hi2_str=sprintf("%d",hi2); \
232 hi2=strtonum(hi2_str);\
233 lo=hi-(hi2*65536); \
234 printf("%d",lo); \
235 } \
236 } \
237 }'`
238 ssidhi_int=`echo $ssid | awk \
239 '{ \
240 len=length($0); \
241 beg=substr($0,1,2); \
242 if ( beg == "0x" ) { \
243 dig = len - 2; \
244 if (dig <= 0 || \
245 dig > 8) { \
246 exit; \
247 } \
248 if (dig < 4) { \
249 print 0; \
250 exit; \
251 } \
252 dig -= 4; \
253 hi=sprintf("0x%s",substr($0,len-4-dig+1,dig)); \
254 print strtonum(hi);\
255 } else { \
256 hi=strtonum($0); \
257 if (hi >= 65536) { \
258 hi = hi / 65536; \
259 printf ("%d",hi);\
260 } else { \
261 printf ("0"); \
262 } \
263 } \
264 }'`
265 if [ "$ssidhi_int" == "" -o \
266 "$ssidlo_int" == "" ]; then
267 return 0;
268 fi
269 return 1
270 }
273 #Update the grub configuration file.
274 #Search for existing entries and replace the current
275 #policy entry with the policy passed to this script
276 #
277 #Arguments passed to this function
278 # 1st : the grub configuration file with full path
279 # 2nd : the binary policy file name, i.e. chwall.bin
280 # 3rd : the name or pattern of the linux kernel name to match
281 # (this determines where the module entry will be made)
282 #
283 # The algorithm here is based on pattern matching
284 # and is working correctly if
285 # - under a title a line beginning with 'kernel' is found
286 # whose following item ends with "xen.gz"
287 # Example: kernel /xen.gz dom0_mem=....
288 # - a module line matching the 3rd parameter is found
289 #
290 updateGrub ()
291 {
292 grubconf=$1
293 policyfile=$2
294 linux=$3
296 tmpfile="/tmp/new_grub.conf"
298 cat $grubconf | \
299 awk -vpolicy=$policyfile \
300 -vlinux=$linux '{ \
301 if ( $1 == "title" ) { \
302 kernelfound = 0; \
303 if ( policymaycome == 1 ){ \
304 printf ("\tmodule %s%s\n", path, policy); \
305 } \
306 policymaycome = 0; \
307 } \
308 else if ( $1 == "kernel" ) { \
309 if ( match($2,"xen.gz$") ) { \
310 path=substr($2,1,RSTART-1); \
311 kernelfound = 1; \
312 } \
313 } \
314 else if ( $1 == "module" && \
315 kernelfound == 1 && \
316 match($2,linux) ) { \
317 policymaycome = 1; \
318 } \
319 else if ( $1 == "module" && \
320 kernelfound == 1 && \
321 policymaycome == 1 && \
322 match($2,"[0-9a-zA-Z]*.bin$") ) { \
323 printf ("\tmodule %s%s\n", path, policy); \
324 policymaycome = 0; \
325 kernelfound = 0; \
326 dontprint = 1; \
327 } \
328 else if ( $1 == "" && \
329 kernelfound == 1 && \
330 policymaycome == 1) { \
331 dontprint = 1; \
332 } \
333 if (dontprint == 0) { \
334 printf ("%s\n", $0); \
335 } \
336 dontprint = 0; \
337 } END { \
338 if ( policymaycome == 1 ) { \
339 printf ("\tmodule %s%s\n", path, policy); \
340 } \
341 }' > $tmpfile
342 if [ ! -r $tmpfile ]; then
343 echo "Could not create temporary file! Aborting."
344 exit -1
345 fi
346 mv -f $tmpfile $grubconf
347 }
350 # Display all the labels in a given mapfile
351 # Parameters
352 # 1st: Full or relative path to the policy's mapfile
353 showLabels ()
354 {
355 mapfile=$1
356 if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
357 echo "Cannot read from vm configuration file $vmfile."
358 return -1
359 fi
361 getPrimaryPolicy $mapfile
362 getSecondaryPolicy $mapfile
364 echo "The following labels are available:"
365 let line=1
366 while [ 1 ]; do
367 ITEM=`cat $mapfile | \
368 awk -vline=$line \
369 -vprimary=$primary \
370 '{ \
371 if ($1 == "LABEL->SSID" && \
372 $2 == "VM" && \
373 $3 == primary ) { \
374 ctr++; \
375 if (ctr == line) { \
376 print $4; \
377 } \
378 } \
379 } END { \
380 }'`
382 if [ "$ITEM" == "" ]; then
383 break
384 fi
385 if [ "$secondary" != "NULL" ]; then
386 LABEL=`cat $mapfile | \
387 awk -vitem=$ITEM \
388 '{
389 if ($1 == "LABEL->SSID" && \
390 $2 == "VM" && \
391 $3 == "CHWALL" && \
392 $4 == item ) { \
393 result = item; \
394 } \
395 } END { \
396 print result \
397 }'`
398 else
399 LABEL=$ITEM
400 fi
402 if [ "$LABEL" != "" ]; then
403 echo "$LABEL"
404 found=1
405 fi
406 let line=line+1
407 done
408 if [ "$found" != "1" ]; then
409 echo "No labels found."
410 fi
411 }
414 # Get the default SSID given a mapfile and the policy name
415 # Parameters
416 # 1st: Full or relative path to the policy's mapfile
417 # 2nd: the name of the policy
418 getDefaultSsid ()
419 {
420 mapfile=$1
421 pol=$2
422 RES=`cat $mapfile \
423 awk -vpol=$pol \
424 { \
425 if ($1 == "LABEL->SSID" && \
426 $2 == "ANY" && \
427 $3 == pol && \
428 $4 == "DEFAULT" ) {\
429 res=$5; \
430 } \
431 } END { \
432 printf "%04x", strtonum(res) \
433 }'`
434 echo "default NULL mapping is $RES"
435 defaultssid=$RES
436 }
439 #Relabel a VM configuration file
440 # Parameters
441 # 1st: Full or relative path to the VM configuration file
442 # 2nd: The label to translate into an ssidref
443 # 3rd: Full or relative path to the policy's map file
444 # 4th: The mode this function is supposed to operate in:
445 # 'relabel' : Relabels the file without querying the user
446 # other : Prompts the user whether to proceed
447 relabel ()
448 {
449 vmfile=$1
450 label=$2
451 mapfile=$3
452 mode=$4
454 if [ ! -r "$vmfile" ]; then
455 echo "Cannot read from vm configuration file $vmfile."
456 return -1
457 fi
459 if [ ! -w "$vmfile" ]; then
460 echo "Cannot write to vm configuration file $vmfile."
461 return -1
462 fi
464 if [ ! -r "$mapfile" ] ; then
465 echo "Cannot read mapping file $mapfile."
466 return -1
467 fi
469 # Determine which policy is primary, which sec.
470 getPrimaryPolicy $mapfile
471 getSecondaryPolicy $mapfile
473 # Calculate the primary policy's SSIDREF
474 if [ "$primary" == "NULL" ]; then
475 SSIDLO="0001"
476 else
477 SSIDLO=`cat $mapfile | \
478 awk -vlabel=$label \
479 -vprimary=$primary \
480 '{ \
481 if ( $1 == "LABEL->SSID" && \
482 $2 == "VM" && \
483 $3 == primary && \
484 $4 == label ) { \
485 result=$5 \
486 } \
487 } END { \
488 if (result != "" ) \
489 {printf "%04x", strtonum(result)}\
490 }'`
491 fi
493 # Calculate the secondary policy's SSIDREF
494 if [ "$secondary" == "NULL" ]; then
495 if [ "$primary" == "NULL" ]; then
496 SSIDHI="0001"
497 else
498 SSIDHI="0000"
499 fi
500 else
501 SSIDHI=`cat $mapfile | \
502 awk -vlabel=$label \
503 -vsecondary=$secondary \
504 '{ \
505 if ( $1 == "LABEL->SSID" && \
506 $2 == "VM" && \
507 $3 == secondary && \
508 $4 == label ) { \
509 result=$5 \
510 } \
511 } END { \
512 if (result != "" ) \
513 {printf "%04x", strtonum(result)}\
514 }'`
515 fi
517 if [ "$SSIDLO" == "" -o \
518 "$SSIDHI" == "" ]; then
519 echo "Could not map the given label '$label'."
520 return -1
521 fi
523 ACM_POLICY=`cat $mapfile | \
524 awk ' { if ( $1 == "POLICY" ) { \
525 result=$2 \
526 } \
527 } \
528 END { \
529 if (result != "") { \
530 printf result \
531 } \
532 }'`
534 if [ "$ACM_POLICY" == "" ]; then
535 echo "Could not find 'POLICY' entry in map file."
536 return -1
537 fi
539 SSIDREF="0x$SSIDHI$SSIDLO"
541 if [ "$mode" != "relabel" ]; then
542 RES=`cat $vmfile | \
543 awk '{ \
544 if ( substr($1,0,7) == "ssidref" ) {\
545 print $0; \
546 } \
547 }'`
548 if [ "$RES" != "" ]; then
549 echo "Do you want to overwrite the existing mapping ($RES)? (y/N)"
550 read user
551 if [ "$user" != "y" -a "$user" != "Y" ]; then
552 echo "Aborted."
553 return 0
554 fi
555 fi
556 fi
558 #Write the output
559 vmtmp1="/tmp/__setlabel.tmp1"
560 vmtmp2="/tmp/__setlabel.tmp2"
561 touch $vmtmp1
562 touch $vmtmp2
563 if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then
564 echo "Cannot create temporary files. Aborting."
565 return -1
566 fi
567 RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1`
568 RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2`
569 RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1`
570 echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1
571 echo "#ACM_LABEL=$label" >> $vmtmp1
572 echo "ssidref = $SSIDREF" >> $vmtmp1
573 mv -f $vmtmp1 $vmfile
574 rm -rf $vmtmp1 $vmtmp2
575 echo "Mapped label '$label' to ssidref '$SSIDREF'."
576 }
579 # Translate an ssidref into its label. This does the reverse lookup
580 # to the relabel function above.
581 # This function displays the results.
582 # Parameters:
583 # 1st: The ssidref to translate; must be in the form '0x00010002'
584 # 2nd: Full or relative path to the policy's mapfile
585 translateSSIDREF ()
586 {
587 ssidref=$1
588 mapfile=$2
590 if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then
591 echo "Cannot read from vm configuration file $vmfile."
592 return -1
593 fi
595 getPrimaryPolicy $mapfile
596 getSecondaryPolicy $mapfile
598 if [ "$primary" == "NULL" -a "$secondary" == "NULL" ]; then
599 echo "There are no labels for the NULL policy."
600 return
601 fi
603 getSSIDLOHI $ssidref
604 ret=$?
605 if [ $ret -ne 1 ]; then
606 echo "Error while parsing the ssid ref number '$ssidref'."
607 fi;
609 let line1=0
610 let line2=0
611 while [ 1 ]; do
612 ITEM1=`cat $mapfile | \
613 awk -vprimary=$primary \
614 -vssidlo=$ssidlo_int \
615 -vline=$line1 \
616 '{ \
617 if ( $1 == "LABEL->SSID" && \
618 $3 == primary && \
619 int($5) == ssidlo ) { \
620 if (l == line) { \
621 print $4; \
622 exit; \
623 } \
624 l++; \
625 } \
626 }'`
628 ITEM2=`cat $mapfile | \
629 awk -vsecondary=$secondary \
630 -vssidhi=$ssidhi_int \
631 -vline=$line2 \
632 '{ \
633 if ( $1 == "LABEL->SSID" && \
634 $3 == secondary && \
635 int($5) == ssidhi ) { \
636 if (l == line) { \
637 print $4; \
638 exit; \
639 } \
640 l++; \
641 } \
642 }'`
644 if [ "$secondary" != "NULL" ]; then
645 if [ "$ITEM1" == "" ]; then
646 let line1=0
647 let line2=line2+1
648 else
649 let line1=line1+1
650 fi
652 if [ "$ITEM1" == "" -a \
653 "$ITEM2" == "" ]; then
654 echo "Could not determine the referenced label."
655 break
656 fi
658 if [ "$ITEM1" == "$ITEM2" ]; then
659 echo "Label: $ITEM1"
660 break
661 fi
662 else
663 if [ "$ITEM1" != "" ]; then
664 echo "Label: $ITEM1"
665 else
666 if [ "$found" == "0" ]; then
667 found=1
668 else
669 break
670 fi
671 fi
672 let line1=line1+1
673 fi
674 done
675 }