You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

95 lines
2.8 KiB

  1. /*
  2. * virt-login-shell.c: a setuid shell to connect to a container
  3. *
  4. * Copyright (C) 2019 Red Hat, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <unistd.h>
  22. #include <sys/types.h>
  23. #include <assert.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <errno.h>
  27. #include <string.h>
  28. #include "configmake.h"
  29. #define VIR_INT64_STR_BUFLEN 21
  30. int main(int argc, char **argv) {
  31. char uidstr[VIR_INT64_STR_BUFLEN];
  32. char gidstr[VIR_INT64_STR_BUFLEN];
  33. const char * newargv[6];
  34. size_t nargs = 0;
  35. char *newenv[] = {
  36. NULL,
  37. NULL,
  38. };
  39. char *term = getenv("TERM");
  40. if (getuid() == 0 || getgid() == 0) {
  41. fprintf(stderr, "%s: must not be run as root\n", argv[0]);
  42. exit(EXIT_FAILURE);
  43. }
  44. if (geteuid() != 0) {
  45. fprintf(stderr, "%s: must be run as setuid root\n", argv[0]);
  46. exit(EXIT_FAILURE);
  47. }
  48. newargv[nargs++] = LIBEXECDIR "/virt-login-shell-helper";
  49. if (argc == 3) {
  50. if (strcmp(argv[1], "-c") != 0) {
  51. fprintf(stderr, "%s: syntax: %s [-c CMDSTR]\n", argv[0], argv[0]);
  52. exit(EXIT_FAILURE);
  53. }
  54. newargv[nargs++] = argv[1];
  55. newargv[nargs++] = argv[2];
  56. } else if (argc != 1) {
  57. fprintf(stderr, "%s: syntax: %s [-c CMDSTR]\n", argv[0], argv[0]);
  58. exit(EXIT_FAILURE);
  59. }
  60. newargv[nargs++] = uidstr;
  61. newargv[nargs++] = gidstr;
  62. newargv[nargs++] = NULL;
  63. assert(nargs <= (sizeof(newargv)/sizeof(newargv[0])));
  64. if (term &&
  65. asprintf(&(newenv[0]), "TERM=%s", term) < 0) {
  66. fprintf(stderr, "%s: cannot set TERM env variable: %s\n",
  67. argv[0], strerror(errno));
  68. exit(EXIT_FAILURE);
  69. }
  70. assert(snprintf(uidstr, sizeof(uidstr), "%d", getuid()) < sizeof(uidstr));
  71. assert(snprintf(gidstr, sizeof(gidstr), "%d", getgid()) < sizeof(gidstr));
  72. if (setuid(0) < 0) {
  73. fprintf(stderr, "%s: unable to set real UID to root: %s\n",
  74. argv[0], strerror(errno));
  75. exit(EXIT_FAILURE);
  76. }
  77. execve(newargv[0], (char *const*)newargv, newenv);
  78. fprintf(stderr, "%s: failed to run %s/virt-login-shell-helper: %s\n",
  79. argv[0], LIBEXECDIR, strerror(errno));
  80. exit(EXIT_FAILURE);
  81. }