* Add a dynamic parameter allow. , or allow. . . Return * its associated bit in the pr_allow bitmask, or zero if the parameter was * not created. */
| 4063 | * not created. |
| 4064 | */ |
| 4065 | unsigned |
| 4066 | prison_add_allow(const char *prefix, const char *name, const char *prefix_descr, |
| 4067 | const char *descr) |
| 4068 | { |
| 4069 | struct bool_flags *bf; |
| 4070 | struct sysctl_oid *parent; |
| 4071 | char *allow_name, *allow_noname, *allowed; |
| 4072 | #ifndef NO_SYSCTL_DESCR |
| 4073 | char *descr_deprecated; |
| 4074 | #endif |
| 4075 | u_int allow_flag; |
| 4076 | |
| 4077 | if (prefix |
| 4078 | ? asprintf(&allow_name, M_PRISON, "allow.%s.%s", prefix, name) |
| 4079 | < 0 || |
| 4080 | asprintf(&allow_noname, M_PRISON, "allow.%s.no%s", prefix, name) |
| 4081 | < 0 |
| 4082 | : asprintf(&allow_name, M_PRISON, "allow.%s", name) < 0 || |
| 4083 | asprintf(&allow_noname, M_PRISON, "allow.no%s", name) < 0) { |
| 4084 | free(allow_name, M_PRISON); |
| 4085 | return 0; |
| 4086 | } |
| 4087 | |
| 4088 | /* |
| 4089 | * See if this parameter has already beed added, i.e. a module was |
| 4090 | * previously loaded/unloaded. |
| 4091 | */ |
| 4092 | mtx_lock(&prison0.pr_mtx); |
| 4093 | for (bf = pr_flag_allow; |
| 4094 | bf < pr_flag_allow + nitems(pr_flag_allow) && |
| 4095 | atomic_load_int(&bf->flag) != 0; |
| 4096 | bf++) { |
| 4097 | if (strcmp(bf->name, allow_name) == 0) { |
| 4098 | allow_flag = bf->flag; |
| 4099 | goto no_add; |
| 4100 | } |
| 4101 | } |
| 4102 | |
| 4103 | /* |
| 4104 | * Find a free bit in pr_allow_all, failing if there are none |
| 4105 | * (which shouldn't happen as long as we keep track of how many |
| 4106 | * potential dynamic flags exist). |
| 4107 | */ |
| 4108 | for (allow_flag = 1;; allow_flag <<= 1) { |
| 4109 | if (allow_flag == 0) |
| 4110 | goto no_add; |
| 4111 | if ((pr_allow_all & allow_flag) == 0) |
| 4112 | break; |
| 4113 | } |
| 4114 | |
| 4115 | /* Note the parameter in the next open slot in pr_flag_allow. */ |
| 4116 | for (bf = pr_flag_allow; ; bf++) { |
| 4117 | if (bf == pr_flag_allow + nitems(pr_flag_allow)) { |
| 4118 | /* This should never happen, but is not fatal. */ |
| 4119 | allow_flag = 0; |
| 4120 | goto no_add; |
| 4121 | } |
| 4122 | if (atomic_load_int(&bf->flag) == 0) |
no test coverage detected