Seccomp.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. 'use strict';
  16. var Os = require('os');
  17. var TEST_PROGRAM = [
  18. "#include <sys/resource.h>",
  19. "#include <sys/prctl.h>",
  20. "#include <linux/filter.h>",
  21. "#include <linux/seccomp.h>",
  22. "#include <linux/audit.h>",
  23. "#include <sys/syscall.h>",
  24. "int main() {",
  25. " return __NR_read",
  26. " | PR_SET_NO_NEW_PRIVS | PR_SET_SECCOMP | AUDIT_ARCH_X86_64",
  27. " | BPF_K | SECCOMP_MODE_FILTER;",
  28. "}"
  29. ].join('\n');
  30. // Turns a version string into an array of integers
  31. // 1.2.3-4-generic-x-5 -> [1, 2, 3, 4, 5]
  32. // 1.2.3-xx-14.2 -> [1, 2, 3, 14, 2]
  33. // 3.2.0-23-generic-pae -> [3, 2, 0, 23]
  34. var version_to_array = function (version) {
  35. var ver_list =
  36. version.replace(/[^0-9]/g, '.').replace(/\.+/g, '.').replace(/\.$/, '').split('.');
  37. for (var i = 0; i < ver_list.length; i++) {
  38. ver_list[i] = Number(ver_list[i]);
  39. }
  40. return ver_list;
  41. };
  42. // Compares two arrays of integers
  43. // Returns
  44. // -1 for version1 < version2
  45. // 0 for version1 == version2
  46. // 1 for version1 > version2
  47. var compare_versions = function (version1, version2) {
  48. if (version1.length === 0 && version2.length === 0) {
  49. return 0;
  50. } else if (version1.length === 0) {
  51. return (version2[0] === 0) ? 0 : 1;
  52. } else if (version2.length === 0) {
  53. return (version1[0] === 0) ? 0 : -1;
  54. } else if (version1[0] === version2[0]) {
  55. return compare_versions(version1.splice(1), version2.splice(1));
  56. } else {
  57. return (version1[0] < version2[0]) ? -1 : 1;
  58. }
  59. };
  60. var seccomp_version_check = function (version) {
  61. var ver_list = version_to_array(version);
  62. return compare_versions(ver_list, [3, 5, 0]);
  63. };
  64. module.exports.detect = function (js, builder)
  65. {
  66. console.log("Searching for SECCOMP");
  67. var osversion = Os.release();
  68. if (builder.config.systemName !== 'linux') {
  69. console.log("SECCOMP is only available on linux");
  70. } else if (process.env['Seccomp_NO']) {
  71. console.log("SECCOMP disabled");
  72. } else if (!builder.config.crossCompiling && (seccomp_version_check(osversion) === -1)) {
  73. console.log("SECCOMP filtering is only available in Linux 3.5+");
  74. } else {
  75. var done = js.async();
  76. var CanCompile = require('../node_build/CanCompile');
  77. var cflags = [ builder.config.cflags, '-x', 'c' ];
  78. CanCompile.check(builder, TEST_PROGRAM, cflags, function (err, can) {
  79. builder.Seccomp_EXISTS = !!can;
  80. if (can) {
  81. console.log("SECCOMP enabled");
  82. js.linkerDependency("util/Seccomp_linux.c");
  83. } else {
  84. console.log("Failed to get SECCOMP, compile failure: [" + err + "]");
  85. js.linkerDependency("util/Seccomp_dummy.c");
  86. }
  87. done();
  88. });
  89. return;
  90. }
  91. js.linkerDependency("util/Seccomp_dummy.c");
  92. };