target.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Helper functions for handling target threads/cpus
  4. *
  5. * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
  6. */
  7. #include "target.h"
  8. #include <pwd.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <linux/kernel.h>
  13. #include <linux/string.h>
  14. enum target_errno target__validate(struct target *target)
  15. {
  16. enum target_errno ret = TARGET_ERRNO__SUCCESS;
  17. if (target->pid)
  18. target->tid = target->pid;
  19. /* CPU and PID are mutually exclusive */
  20. if (target->tid && target->cpu_list) {
  21. target->cpu_list = NULL;
  22. if (ret == TARGET_ERRNO__SUCCESS)
  23. ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
  24. }
  25. /* UID and PID are mutually exclusive */
  26. if (target->tid && target->uid_str) {
  27. target->uid_str = NULL;
  28. if (ret == TARGET_ERRNO__SUCCESS)
  29. ret = TARGET_ERRNO__PID_OVERRIDE_UID;
  30. }
  31. /* UID and CPU are mutually exclusive */
  32. if (target->uid_str && target->cpu_list) {
  33. target->cpu_list = NULL;
  34. if (ret == TARGET_ERRNO__SUCCESS)
  35. ret = TARGET_ERRNO__UID_OVERRIDE_CPU;
  36. }
  37. /* PID and SYSTEM are mutually exclusive */
  38. if (target->tid && target->system_wide) {
  39. target->system_wide = false;
  40. if (ret == TARGET_ERRNO__SUCCESS)
  41. ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
  42. }
  43. /* UID and SYSTEM are mutually exclusive */
  44. if (target->uid_str && target->system_wide) {
  45. target->system_wide = false;
  46. if (ret == TARGET_ERRNO__SUCCESS)
  47. ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
  48. }
  49. /* THREAD and SYSTEM/CPU are mutually exclusive */
  50. if (target->per_thread && (target->system_wide || target->cpu_list)) {
  51. target->per_thread = false;
  52. if (ret == TARGET_ERRNO__SUCCESS)
  53. ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
  54. }
  55. return ret;
  56. }
  57. enum target_errno target__parse_uid(struct target *target)
  58. {
  59. struct passwd pwd, *result;
  60. char buf[1024];
  61. const char *str = target->uid_str;
  62. target->uid = UINT_MAX;
  63. if (str == NULL)
  64. return TARGET_ERRNO__SUCCESS;
  65. /* Try user name first */
  66. getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
  67. if (result == NULL) {
  68. /*
  69. * The user name not found. Maybe it's a UID number.
  70. */
  71. char *endptr;
  72. int uid = strtol(str, &endptr, 10);
  73. if (*endptr != '\0')
  74. return TARGET_ERRNO__INVALID_UID;
  75. getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
  76. if (result == NULL)
  77. return TARGET_ERRNO__USER_NOT_FOUND;
  78. }
  79. target->uid = result->pw_uid;
  80. return TARGET_ERRNO__SUCCESS;
  81. }
  82. /*
  83. * This must have a same ordering as the enum target_errno.
  84. */
  85. static const char *target__error_str[] = {
  86. "PID/TID switch overriding CPU",
  87. "PID/TID switch overriding UID",
  88. "UID switch overriding CPU",
  89. "PID/TID switch overriding SYSTEM",
  90. "UID switch overriding SYSTEM",
  91. "SYSTEM/CPU switch overriding PER-THREAD",
  92. "Invalid User: %s",
  93. "Problems obtaining information for user %s",
  94. };
  95. int target__strerror(struct target *target, int errnum,
  96. char *buf, size_t buflen)
  97. {
  98. int idx;
  99. const char *msg;
  100. BUG_ON(buflen == 0);
  101. if (errnum >= 0) {
  102. str_error_r(errnum, buf, buflen);
  103. return 0;
  104. }
  105. if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
  106. return -1;
  107. idx = errnum - __TARGET_ERRNO__START;
  108. msg = target__error_str[idx];
  109. switch (errnum) {
  110. case TARGET_ERRNO__PID_OVERRIDE_CPU ...
  111. TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
  112. snprintf(buf, buflen, "%s", msg);
  113. break;
  114. case TARGET_ERRNO__INVALID_UID:
  115. case TARGET_ERRNO__USER_NOT_FOUND:
  116. snprintf(buf, buflen, msg, target->uid_str);
  117. break;
  118. default:
  119. /* cannot reach here */
  120. break;
  121. }
  122. return 0;
  123. }