int
work_interval_ctl(__unused proc_t p, struct work_interval_ctl_args *uap,
- __unused int32_t *retval)
+ __unused int32_t *retval)
{
uint32_t operation = uap->operation;
int error = 0;
struct kern_work_interval_create_args create_args;
switch (operation) {
- case WORK_INTERVAL_OPERATION_CREATE:
- return ENOTSUP;
- case WORK_INTERVAL_OPERATION_CREATE2:
- if (uap->arg == USER_ADDR_NULL || uap->work_interval_id != 0)
- return EINVAL;
- if (uap->len < sizeof(create_params))
- return EINVAL;
-
- if ((error = copyin(uap->arg, &create_params, sizeof(create_params))))
- return error;
-
- if ((error = priv_check_cred(kauth_cred_get(), PRIV_WORK_INTERVAL, 0)) != 0) {
- return error;
- }
-
- create_args = (struct kern_work_interval_create_args) {
- .wica_id = create_params.wicp_id,
- .wica_port = create_params.wicp_port,
- .wica_create_flags = create_params.wicp_create_flags,
- };
-
- kret = kern_work_interval_create(current_thread(), &create_args);
-
- /* thread already has a work interval */
- if (kret == KERN_FAILURE)
- return EALREADY;
-
- /* port copyout failed */
- if (kret == KERN_RESOURCE_SHORTAGE)
- return ENOMEM;
-
- /* some other failure */
- if (kret != KERN_SUCCESS)
- return EINVAL;
-
- create_params = (struct work_interval_create_params) {
- .wicp_id = create_args.wica_id,
- .wicp_port = create_args.wica_port,
- .wicp_create_flags = create_args.wica_create_flags,
- };
-
- if ((error = copyout(&create_params, uap->arg, sizeof(create_params)))) {
- kern_work_interval_destroy(current_thread(), create_args.wica_id);
- return error;
- }
- break;
- case WORK_INTERVAL_OPERATION_DESTROY:
- if (uap->arg != USER_ADDR_NULL || uap->work_interval_id == 0) {
- return EINVAL;
- }
-
- /*
- * No privilege check, we assume a previous WORK_INTERVAL_OPERATION_CREATE
- * operation would have allocated a work interval ID for the current
- * thread, which the scheduler will validate.
- */
- kret = kern_work_interval_destroy(current_thread(), uap->work_interval_id);
- if (kret != KERN_SUCCESS)
- return EINVAL;
-
- break;
- case WORK_INTERVAL_OPERATION_NOTIFY:
- if (uap->arg == USER_ADDR_NULL || uap->work_interval_id == 0)
- return EINVAL;
-
- if (uap->len < sizeof(notification))
- return EINVAL;
-
- /*
- * No privilege check, we assume a previous WORK_INTERVAL_OPERATION_CREATE
- * operation would have allocated a work interval ID for the current
- * thread, which the scheduler will validate.
- */
- if ((error = copyin(uap->arg, ¬ification, sizeof(notification))))
- return error;
-
- struct kern_work_interval_args kwi_args = {
- .work_interval_id = uap->work_interval_id,
- .start = notification.start,
- .finish = notification.finish,
- .deadline = notification.deadline,
- .next_start = notification.next_start,
- .notify_flags = notification.notify_flags,
- .create_flags = notification.create_flags,
- };
-
- kret = kern_work_interval_notify(current_thread(), &kwi_args);
- if (kret != KERN_SUCCESS)
- return EINVAL;
-
- break;
- case WORK_INTERVAL_OPERATION_JOIN:
- if (uap->arg != USER_ADDR_NULL) {
- return EINVAL;
- }
-
- /*
- * No privilege check, because the work interval port
- * is a capability.
- */
- kret = kern_work_interval_join(current_thread(),
- (mach_port_name_t)uap->work_interval_id);
- if (kret != KERN_SUCCESS)
- return EINVAL;
-
- break;
-
- default:
- return ENOTSUP;
+ case WORK_INTERVAL_OPERATION_CREATE:
+ return ENOTSUP;
+ case WORK_INTERVAL_OPERATION_CREATE2:
+ if (uap->arg == USER_ADDR_NULL || uap->work_interval_id != 0) {
+ return EINVAL;
+ }
+ if (uap->len < sizeof(create_params)) {
+ return EINVAL;
+ }
+
+ if ((error = copyin(uap->arg, &create_params, sizeof(create_params)))) {
+ return error;
+ }
+
+ if ((error = priv_check_cred(kauth_cred_get(), PRIV_WORK_INTERVAL, 0)) != 0) {
+ return error;
+ }
+
+ create_args = (struct kern_work_interval_create_args) {
+ .wica_id = create_params.wicp_id,
+ .wica_port = create_params.wicp_port,
+ .wica_create_flags = create_params.wicp_create_flags,
+ };
+
+ kret = kern_work_interval_create(current_thread(), &create_args);
+
+ /* thread already has a work interval */
+ if (kret == KERN_FAILURE) {
+ return EALREADY;
+ }
+
+ /* port copyout failed */
+ if (kret == KERN_RESOURCE_SHORTAGE) {
+ return ENOMEM;
+ }
+
+ /* some other failure */
+ if (kret != KERN_SUCCESS) {
+ return EINVAL;
+ }
+
+ create_params = (struct work_interval_create_params) {
+ .wicp_id = create_args.wica_id,
+ .wicp_port = create_args.wica_port,
+ .wicp_create_flags = create_args.wica_create_flags,
+ };
+
+ if ((error = copyout(&create_params, uap->arg, sizeof(create_params)))) {
+ kern_work_interval_destroy(current_thread(), create_args.wica_id);
+ return error;
+ }
+ break;
+ case WORK_INTERVAL_OPERATION_DESTROY:
+ if (uap->arg != USER_ADDR_NULL || uap->work_interval_id == 0) {
+ return EINVAL;
+ }
+
+ /*
+ * No privilege check, we assume a previous WORK_INTERVAL_OPERATION_CREATE
+ * operation would have allocated a work interval ID for the current
+ * thread, which the scheduler will validate.
+ */
+ kret = kern_work_interval_destroy(current_thread(), uap->work_interval_id);
+ if (kret != KERN_SUCCESS) {
+ return EINVAL;
+ }
+
+ break;
+ case WORK_INTERVAL_OPERATION_NOTIFY:
+ if (uap->arg == USER_ADDR_NULL || uap->work_interval_id == 0) {
+ return EINVAL;
+ }
+
+ if (uap->len < sizeof(notification)) {
+ return EINVAL;
+ }
+
+ /*
+ * No privilege check, we assume a previous WORK_INTERVAL_OPERATION_CREATE
+ * operation would have allocated a work interval ID for the current
+ * thread, which the scheduler will validate.
+ */
+ if ((error = copyin(uap->arg, ¬ification, sizeof(notification)))) {
+ return error;
+ }
+
+ struct kern_work_interval_args kwi_args = {
+ .work_interval_id = uap->work_interval_id,
+ .start = notification.start,
+ .finish = notification.finish,
+ .deadline = notification.deadline,
+ .next_start = notification.next_start,
+ .notify_flags = notification.notify_flags,
+ .create_flags = notification.create_flags,
+ };
+
+ kret = kern_work_interval_notify(current_thread(), &kwi_args);
+ if (kret != KERN_SUCCESS) {
+ return EINVAL;
+ }
+
+ break;
+ case WORK_INTERVAL_OPERATION_JOIN:
+ if (uap->arg != USER_ADDR_NULL) {
+ return EINVAL;
+ }
+
+ /*
+ * No privilege check, because the work interval port
+ * is a capability.
+ */
+ kret = kern_work_interval_join(current_thread(),
+ (mach_port_name_t)uap->work_interval_id);
+ if (kret != KERN_SUCCESS) {
+ return EINVAL;
+ }
+
+ break;
+
+ default:
+ return ENOTSUP;
}
- return (error);
+ return error;
}
-