aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/Kconfig14
-rw-r--r--security/integrity/Makefile1
-rw-r--r--security/integrity/digsig.c48
-rw-r--r--security/integrity/evm/evm.h12
-rw-r--r--security/integrity/evm/evm_crypto.c76
-rw-r--r--security/integrity/evm/evm_main.c94
-rw-r--r--security/integrity/ima/ima_api.c4
-rw-r--r--security/integrity/ima/ima_queue.c17
-rw-r--r--security/integrity/integrity.h21
9 files changed, 244 insertions, 43 deletions
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 4bf00acf7937..d384ea921482 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -3,5 +3,19 @@ config INTEGRITY
3 def_bool y 3 def_bool y
4 depends on IMA || EVM 4 depends on IMA || EVM
5 5
6config INTEGRITY_DIGSIG
7 boolean "Digital signature verification using multiple keyrings"
8 depends on INTEGRITY && KEYS
9 default n
10 select DIGSIG
11 help
12 This option enables digital signature verification support
13 using multiple keyrings. It defines separate keyrings for each
14 of the different use cases - evm, ima, and modules.
15 Different keyrings improves search performance, but also allow
16 to "lock" certain keyring to prevent adding new keys.
17 This is useful for evm and module keyrings, when keys are
18 usually only added from initramfs.
19
6source security/integrity/ima/Kconfig 20source security/integrity/ima/Kconfig
7source security/integrity/evm/Kconfig 21source security/integrity/evm/Kconfig
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 0ae44aea6516..bece0563ee5e 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -3,6 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_INTEGRITY) += integrity.o 5obj-$(CONFIG_INTEGRITY) += integrity.o
6obj-$(CONFIG_INTEGRITY_DIGSIG) += digsig.o
6 7
7integrity-y := iint.o 8integrity-y := iint.o
8 9
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
new file mode 100644
index 000000000000..2dc167d7cde9
--- /dev/null
+++ b/security/integrity/digsig.c
@@ -0,0 +1,48 @@
1/*
2 * Copyright (C) 2011 Intel Corporation
3 *
4 * Author:
5 * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2 of the License.
10 *
11 */
12
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15#include <linux/err.h>
16#include <linux/rbtree.h>
17#include <linux/key-type.h>
18#include <linux/digsig.h>
19
20#include "integrity.h"
21
22static struct key *keyring[INTEGRITY_KEYRING_MAX];
23
24static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
25 "_evm",
26 "_module",
27 "_ima",
28};
29
30int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
31 const char *digest, int digestlen)
32{
33 if (id >= INTEGRITY_KEYRING_MAX)
34 return -EINVAL;
35
36 if (!keyring[id]) {
37 keyring[id] =
38 request_key(&key_type_keyring, keyring_name[id], NULL);
39 if (IS_ERR(keyring[id])) {
40 int err = PTR_ERR(keyring[id]);
41 pr_err("no %s keyring: %d\n", keyring_name[id], err);
42 keyring[id] = NULL;
43 return err;
44 }
45 }
46
47 return digsig_verify(keyring[id], sig, siglen, digest, digestlen);
48}
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index d320f5197437..c885247ebcf7 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -12,14 +12,21 @@
12 * File: evm.h 12 * File: evm.h
13 * 13 *
14 */ 14 */
15
16#ifndef __INTEGRITY_EVM_H
17#define __INTEGRITY_EVM_H
18
15#include <linux/xattr.h> 19#include <linux/xattr.h>
16#include <linux/security.h> 20#include <linux/security.h>
21
17#include "../integrity.h" 22#include "../integrity.h"
18 23
19extern int evm_initialized; 24extern int evm_initialized;
20extern char *evm_hmac; 25extern char *evm_hmac;
26extern char *evm_hash;
21 27
22extern struct crypto_shash *hmac_tfm; 28extern struct crypto_shash *hmac_tfm;
29extern struct crypto_shash *hash_tfm;
23 30
24/* List of EVM protected security xattrs */ 31/* List of EVM protected security xattrs */
25extern char *evm_config_xattrnames[]; 32extern char *evm_config_xattrnames[];
@@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry,
32extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, 39extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
33 const char *req_xattr_value, 40 const char *req_xattr_value,
34 size_t req_xattr_value_len, char *digest); 41 size_t req_xattr_value_len, char *digest);
42extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
43 const char *req_xattr_value,
44 size_t req_xattr_value_len, char *digest);
35extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr, 45extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
36 char *hmac_val); 46 char *hmac_val);
37extern int evm_init_secfs(void); 47extern int evm_init_secfs(void);
38extern void evm_cleanup_secfs(void); 48extern void evm_cleanup_secfs(void);
49
50#endif
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 8738deff26fa..49a464f5595b 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -26,44 +26,56 @@ static unsigned char evmkey[MAX_KEY_SIZE];
26static int evmkey_len = MAX_KEY_SIZE; 26static int evmkey_len = MAX_KEY_SIZE;
27 27
28struct crypto_shash *hmac_tfm; 28struct crypto_shash *hmac_tfm;
29struct crypto_shash *hash_tfm;
29 30
30static DEFINE_MUTEX(mutex); 31static DEFINE_MUTEX(mutex);
31 32
32static struct shash_desc *init_desc(void) 33static struct shash_desc *init_desc(char type)
33{ 34{
34 int rc; 35 long rc;
36 char *algo;
37 struct crypto_shash **tfm;
35 struct shash_desc *desc; 38 struct shash_desc *desc;
36 39
37 if (hmac_tfm == NULL) { 40 if (type == EVM_XATTR_HMAC) {
41 tfm = &hmac_tfm;
42 algo = evm_hmac;
43 } else {
44 tfm = &hash_tfm;
45 algo = evm_hash;
46 }
47
48 if (*tfm == NULL) {
38 mutex_lock(&mutex); 49 mutex_lock(&mutex);
39 if (hmac_tfm) 50 if (*tfm)
40 goto out; 51 goto out;
41 hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC); 52 *tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
42 if (IS_ERR(hmac_tfm)) { 53 if (IS_ERR(*tfm)) {
43 pr_err("Can not allocate %s (reason: %ld)\n", 54 rc = PTR_ERR(*tfm);
44 evm_hmac, PTR_ERR(hmac_tfm)); 55 pr_err("Can not allocate %s (reason: %ld)\n", algo, rc);
45 rc = PTR_ERR(hmac_tfm); 56 *tfm = NULL;
46 hmac_tfm = NULL;
47 mutex_unlock(&mutex); 57 mutex_unlock(&mutex);
48 return ERR_PTR(rc); 58 return ERR_PTR(rc);
49 } 59 }
50 rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len); 60 if (type == EVM_XATTR_HMAC) {
51 if (rc) { 61 rc = crypto_shash_setkey(*tfm, evmkey, evmkey_len);
52 crypto_free_shash(hmac_tfm); 62 if (rc) {
53 hmac_tfm = NULL; 63 crypto_free_shash(*tfm);
54 mutex_unlock(&mutex); 64 *tfm = NULL;
55 return ERR_PTR(rc); 65 mutex_unlock(&mutex);
66 return ERR_PTR(rc);
67 }
56 } 68 }
57out: 69out:
58 mutex_unlock(&mutex); 70 mutex_unlock(&mutex);
59 } 71 }
60 72
61 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm), 73 desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
62 GFP_KERNEL); 74 GFP_KERNEL);
63 if (!desc) 75 if (!desc)
64 return ERR_PTR(-ENOMEM); 76 return ERR_PTR(-ENOMEM);
65 77
66 desc->tfm = hmac_tfm; 78 desc->tfm = *tfm;
67 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 79 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
68 80
69 rc = crypto_shash_init(desc); 81 rc = crypto_shash_init(desc);
@@ -108,9 +120,11 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
108 * the hmac using the requested xattr value. Don't alloc/free memory for 120 * the hmac using the requested xattr value. Don't alloc/free memory for
109 * each xattr, but attempt to re-use the previously allocated memory. 121 * each xattr, but attempt to re-use the previously allocated memory.
110 */ 122 */
111int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, 123static int evm_calc_hmac_or_hash(struct dentry *dentry,
112 const char *req_xattr_value, size_t req_xattr_value_len, 124 const char *req_xattr_name,
113 char *digest) 125 const char *req_xattr_value,
126 size_t req_xattr_value_len,
127 char type, char *digest)
114{ 128{
115 struct inode *inode = dentry->d_inode; 129 struct inode *inode = dentry->d_inode;
116 struct shash_desc *desc; 130 struct shash_desc *desc;
@@ -122,7 +136,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
122 136
123 if (!inode->i_op || !inode->i_op->getxattr) 137 if (!inode->i_op || !inode->i_op->getxattr)
124 return -EOPNOTSUPP; 138 return -EOPNOTSUPP;
125 desc = init_desc(); 139 desc = init_desc(type);
126 if (IS_ERR(desc)) 140 if (IS_ERR(desc))
127 return PTR_ERR(desc); 141 return PTR_ERR(desc);
128 142
@@ -156,6 +170,22 @@ out:
156 return error; 170 return error;
157} 171}
158 172
173int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
174 const char *req_xattr_value, size_t req_xattr_value_len,
175 char *digest)
176{
177 return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
178 req_xattr_value_len, EVM_XATTR_HMAC, digest);
179}
180
181int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
182 const char *req_xattr_value, size_t req_xattr_value_len,
183 char *digest)
184{
185 return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
186 req_xattr_value_len, IMA_XATTR_DIGEST, digest);
187}
188
159/* 189/*
160 * Calculate the hmac and update security.evm xattr 190 * Calculate the hmac and update security.evm xattr
161 * 191 *
@@ -186,7 +216,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
186{ 216{
187 struct shash_desc *desc; 217 struct shash_desc *desc;
188 218
189 desc = init_desc(); 219 desc = init_desc(EVM_XATTR_HMAC);
190 if (IS_ERR(desc)) { 220 if (IS_ERR(desc)) {
191 printk(KERN_INFO "init_desc failed\n"); 221 printk(KERN_INFO "init_desc failed\n");
192 return PTR_ERR(desc); 222 return PTR_ERR(desc);
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 92d3d99a9f7b..8901501425f4 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -25,6 +25,7 @@
25int evm_initialized; 25int evm_initialized;
26 26
27char *evm_hmac = "hmac(sha1)"; 27char *evm_hmac = "hmac(sha1)";
28char *evm_hash = "sha1";
28 29
29char *evm_config_xattrnames[] = { 30char *evm_config_xattrnames[] = {
30#ifdef CONFIG_SECURITY_SELINUX 31#ifdef CONFIG_SECURITY_SELINUX
@@ -46,6 +47,29 @@ static int __init evm_set_fixmode(char *str)
46} 47}
47__setup("evm=", evm_set_fixmode); 48__setup("evm=", evm_set_fixmode);
48 49
50static int evm_find_protected_xattrs(struct dentry *dentry)
51{
52 struct inode *inode = dentry->d_inode;
53 char **xattr;
54 int error;
55 int count = 0;
56
57 if (!inode->i_op || !inode->i_op->getxattr)
58 return -EOPNOTSUPP;
59
60 for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
61 error = inode->i_op->getxattr(dentry, *xattr, NULL, 0);
62 if (error < 0) {
63 if (error == -ENODATA)
64 continue;
65 return error;
66 }
67 count++;
68 }
69
70 return count;
71}
72
49/* 73/*
50 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr 74 * evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
51 * 75 *
@@ -65,32 +89,72 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
65 size_t xattr_value_len, 89 size_t xattr_value_len,
66 struct integrity_iint_cache *iint) 90 struct integrity_iint_cache *iint)
67{ 91{
68 struct evm_ima_xattr_data xattr_data; 92 struct evm_ima_xattr_data *xattr_data = NULL;
93 struct evm_ima_xattr_data calc;
69 enum integrity_status evm_status = INTEGRITY_PASS; 94 enum integrity_status evm_status = INTEGRITY_PASS;
70 int rc; 95 int rc, xattr_len;
71 96
72 if (iint && iint->evm_status == INTEGRITY_PASS) 97 if (iint && iint->evm_status == INTEGRITY_PASS)
73 return iint->evm_status; 98 return iint->evm_status;
74 99
75 /* if status is not PASS, try to check again - against -ENOMEM */ 100 /* if status is not PASS, try to check again - against -ENOMEM */
76 101
77 rc = evm_calc_hmac(dentry, xattr_name, xattr_value, 102 /* first need to know the sig type */
78 xattr_value_len, xattr_data.digest); 103 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
79 if (rc < 0) { 104 GFP_NOFS);
80 evm_status = (rc == -ENODATA) 105 if (rc <= 0) {
81 ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL; 106 if (rc == 0)
107 evm_status = INTEGRITY_FAIL; /* empty */
108 else if (rc == -ENODATA) {
109 rc = evm_find_protected_xattrs(dentry);
110 if (rc > 0)
111 evm_status = INTEGRITY_NOLABEL;
112 else if (rc == 0)
113 evm_status = INTEGRITY_NOXATTRS; /* new file */
114 }
82 goto out; 115 goto out;
83 } 116 }
84 117
85 xattr_data.type = EVM_XATTR_HMAC; 118 xattr_len = rc - 1;
86 rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data, 119
87 sizeof xattr_data, GFP_NOFS); 120 /* check value type */
88 if (rc < 0) 121 switch (xattr_data->type) {
89 evm_status = (rc == -ENODATA) 122 case EVM_XATTR_HMAC:
90 ? INTEGRITY_NOLABEL : INTEGRITY_FAIL; 123 rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
124 xattr_value_len, calc.digest);
125 if (rc)
126 break;
127 rc = memcmp(xattr_data->digest, calc.digest,
128 sizeof(calc.digest));
129 if (rc)
130 rc = -EINVAL;
131 break;
132 case EVM_IMA_XATTR_DIGSIG:
133 rc = evm_calc_hash(dentry, xattr_name, xattr_value,
134 xattr_value_len, calc.digest);
135 if (rc)
136 break;
137 rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
138 xattr_data->digest, xattr_len,
139 calc.digest, sizeof(calc.digest));
140 if (!rc) {
141 /* we probably want to replace rsa with hmac here */
142 evm_update_evmxattr(dentry, xattr_name, xattr_value,
143 xattr_value_len);
144 }
145 break;
146 default:
147 rc = -EINVAL;
148 break;
149 }
150
151 if (rc)
152 evm_status = (rc == -ENODATA) ?
153 INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
91out: 154out:
92 if (iint) 155 if (iint)
93 iint->evm_status = evm_status; 156 iint->evm_status = evm_status;
157 kfree(xattr_data);
94 return evm_status; 158 return evm_status;
95} 159}
96 160
@@ -354,6 +418,8 @@ static int __init init_evm(void)
354 printk(KERN_INFO "EVM: Error registering secfs\n"); 418 printk(KERN_INFO "EVM: Error registering secfs\n");
355 goto err; 419 goto err;
356 } 420 }
421
422 return 0;
357err: 423err:
358 return error; 424 return error;
359} 425}
@@ -363,6 +429,8 @@ static void __exit cleanup_evm(void)
363 evm_cleanup_secfs(); 429 evm_cleanup_secfs();
364 if (hmac_tfm) 430 if (hmac_tfm)
365 crypto_free_shash(hmac_tfm); 431 crypto_free_shash(hmac_tfm);
432 if (hash_tfm)
433 crypto_free_shash(hash_tfm);
366} 434}
367 435
368/* 436/*
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 0d50df04ccc4..88a2788b981d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -178,8 +178,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
178 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX); 178 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
179 179
180 result = ima_store_template(entry, violation, inode); 180 result = ima_store_template(entry, violation, inode);
181 if (!result) 181 if (!result || result == -EEXIST)
182 iint->flags |= IMA_MEASURED; 182 iint->flags |= IMA_MEASURED;
183 else 183 if (result < 0)
184 kfree(entry); 184 kfree(entry);
185} 185}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 8e28f04a5e2e..55a6271bce7a 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -23,6 +23,8 @@
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include "ima.h" 24#include "ima.h"
25 25
26#define AUDIT_CAUSE_LEN_MAX 32
27
26LIST_HEAD(ima_measurements); /* list of all measurements */ 28LIST_HEAD(ima_measurements); /* list of all measurements */
27 29
28/* key: inode (before secure-hashing a file) */ 30/* key: inode (before secure-hashing a file) */
@@ -94,7 +96,8 @@ static int ima_pcr_extend(const u8 *hash)
94 96
95 result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash); 97 result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
96 if (result != 0) 98 if (result != 0)
97 pr_err("IMA: Error Communicating to TPM chip\n"); 99 pr_err("IMA: Error Communicating to TPM chip, result: %d\n",
100 result);
98 return result; 101 return result;
99} 102}
100 103
@@ -106,14 +109,16 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
106{ 109{
107 u8 digest[IMA_DIGEST_SIZE]; 110 u8 digest[IMA_DIGEST_SIZE];
108 const char *audit_cause = "hash_added"; 111 const char *audit_cause = "hash_added";
112 char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX];
109 int audit_info = 1; 113 int audit_info = 1;
110 int result = 0; 114 int result = 0, tpmresult = 0;
111 115
112 mutex_lock(&ima_extend_list_mutex); 116 mutex_lock(&ima_extend_list_mutex);
113 if (!violation) { 117 if (!violation) {
114 memcpy(digest, entry->digest, sizeof digest); 118 memcpy(digest, entry->digest, sizeof digest);
115 if (ima_lookup_digest_entry(digest)) { 119 if (ima_lookup_digest_entry(digest)) {
116 audit_cause = "hash_exists"; 120 audit_cause = "hash_exists";
121 result = -EEXIST;
117 goto out; 122 goto out;
118 } 123 }
119 } 124 }
@@ -128,9 +133,11 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
128 if (violation) /* invalidate pcr */ 133 if (violation) /* invalidate pcr */
129 memset(digest, 0xff, sizeof digest); 134 memset(digest, 0xff, sizeof digest);
130 135
131 result = ima_pcr_extend(digest); 136 tpmresult = ima_pcr_extend(digest);
132 if (result != 0) { 137 if (tpmresult != 0) {
133 audit_cause = "TPM error"; 138 snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)",
139 tpmresult);
140 audit_cause = tpm_audit_cause;
134 audit_info = 0; 141 audit_info = 0;
135 } 142 }
136out: 143out:
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 3143a3c39868..4da6ba81d153 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -46,5 +46,26 @@ struct integrity_iint_cache {
46struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); 46struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
47struct integrity_iint_cache *integrity_iint_find(struct inode *inode); 47struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
48 48
49#define INTEGRITY_KEYRING_EVM 0
50#define INTEGRITY_KEYRING_MODULE 1
51#define INTEGRITY_KEYRING_IMA 2
52#define INTEGRITY_KEYRING_MAX 3
53
54#ifdef CONFIG_INTEGRITY_DIGSIG
55
56int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
57 const char *digest, int digestlen);
58
59#else
60
61static inline int integrity_digsig_verify(const unsigned int id,
62 const char *sig, int siglen,
63 const char *digest, int digestlen)
64{
65 return -EOPNOTSUPP;
66}
67
68#endif /* CONFIG_INTEGRITY_DIGSIG */
69
49/* set during initialization */ 70/* set during initialization */
50extern int iint_initialized; 71extern int iint_initialized;