diff options
author | netblue30 <netblue30@protonmail.com> | 2021-02-26 07:06:39 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-26 07:06:39 -0500 |
commit | 5d88ee8957dc38a52c36f71b91c786dbec9d4ec9 (patch) | |
tree | 4b8058048ba99de070f46af382dd45b98820d476 /src | |
parent | Merge pull request #4010 from Tomin1/mkdir_and_mkfile_options (diff) | |
parent | Allow changing "protocol" list after initial set (diff) | |
download | firejail-5d88ee8957dc38a52c36f71b91c786dbec9d4ec9.tar.gz firejail-5d88ee8957dc38a52c36f71b91c786dbec9d4ec9.tar.zst firejail-5d88ee8957dc38a52c36f71b91c786dbec9d4ec9.zip |
Merge pull request #4009 from Tomin1/protocol_list_improvements
Allow changing protocol list after initial set
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/main.c | 13 | ||||
-rw-r--r-- | src/firejail/profile.c | 153 |
3 files changed, 151 insertions, 18 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 36340ff2c..c8080f778 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -451,6 +451,9 @@ int profile_check_line(char *ptr, int lineno, const char *fname); | |||
451 | // add a profile entry in cfg.profile list; use str to populate the list | 451 | // add a profile entry in cfg.profile list; use str to populate the list |
452 | void profile_add(char *str); | 452 | void profile_add(char *str); |
453 | void profile_add_ignore(const char *str); | 453 | void profile_add_ignore(const char *str); |
454 | char *profile_list_normalize(char *list); | ||
455 | char *profile_list_compress(char *list); | ||
456 | void profile_list_augment(char **list, const char *items); | ||
454 | 457 | ||
455 | // list.c | 458 | // list.c |
456 | void list(void); | 459 | void list(void); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 3c8667829..9b4f2bc60 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1285,15 +1285,10 @@ int main(int argc, char **argv, char **envp) { | |||
1285 | #endif | 1285 | #endif |
1286 | else if (strncmp(argv[i], "--protocol=", 11) == 0) { | 1286 | else if (strncmp(argv[i], "--protocol=", 11) == 0) { |
1287 | if (checkcfg(CFG_SECCOMP)) { | 1287 | if (checkcfg(CFG_SECCOMP)) { |
1288 | if (cfg.protocol) { | 1288 | const char *add = argv[i] + 11; |
1289 | fwarning("more than one protocol list is present, \"%s\" will be installed\n", cfg.protocol); | 1289 | profile_list_augment(&cfg.protocol, add); |
1290 | } | 1290 | if (arg_debug) |
1291 | else { | 1291 | fprintf(stderr, "[option] combined protocol list: \"%s\"\n", cfg.protocol); |
1292 | // store list | ||
1293 | cfg.protocol = strdup(argv[i] + 11); | ||
1294 | if (!cfg.protocol) | ||
1295 | errExit("strdup"); | ||
1296 | } | ||
1297 | } | 1292 | } |
1298 | else | 1293 | else |
1299 | exit_err_feature("seccomp"); | 1294 | exit_err_feature("seccomp"); |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 9339228f4..f3266c23e 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -911,15 +911,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
911 | 911 | ||
912 | if (strncmp(ptr, "protocol ", 9) == 0) { | 912 | if (strncmp(ptr, "protocol ", 9) == 0) { |
913 | if (checkcfg(CFG_SECCOMP)) { | 913 | if (checkcfg(CFG_SECCOMP)) { |
914 | if (cfg.protocol) { | 914 | const char *add = ptr + 9; |
915 | fwarning("more than one protocol list is present, \"%s\" will be installed\n", cfg.protocol); | 915 | profile_list_augment(&cfg.protocol, add); |
916 | return 0; | 916 | if (arg_debug) |
917 | } | 917 | fprintf(stderr, "[profile] combined protocol list: \"%s\"\n", cfg.protocol); |
918 | |||
919 | // store list | ||
920 | cfg.protocol = strdup(ptr + 9); | ||
921 | if (!cfg.protocol) | ||
922 | errExit("strdup"); | ||
923 | } | 918 | } |
924 | else | 919 | else |
925 | warning_feature_disabled("seccomp"); | 920 | warning_feature_disabled("seccomp"); |
@@ -1773,3 +1768,143 @@ void profile_read(const char *fname) { | |||
1773 | } | 1768 | } |
1774 | fclose(fp); | 1769 | fclose(fp); |
1775 | } | 1770 | } |
1771 | |||
1772 | char *profile_list_normalize(char *list) | ||
1773 | { | ||
1774 | /* Remove redundant commas. | ||
1775 | * | ||
1776 | * As result is always shorter than original, | ||
1777 | * in-place copying can be used. | ||
1778 | */ | ||
1779 | size_t i = 0; | ||
1780 | size_t j = 0; | ||
1781 | int c; | ||
1782 | while (list[i] == ',') | ||
1783 | ++i; | ||
1784 | while ((c = list[i++])) { | ||
1785 | if (c == ',') { | ||
1786 | while (list[i] == ',') | ||
1787 | ++i; | ||
1788 | if (list[i] == 0) | ||
1789 | break; | ||
1790 | } | ||
1791 | list[j++] = c; | ||
1792 | } | ||
1793 | list[j] = 0; | ||
1794 | return list; | ||
1795 | } | ||
1796 | |||
1797 | char *profile_list_compress(char *list) | ||
1798 | { | ||
1799 | size_t i; | ||
1800 | |||
1801 | /* Comma separated list is processed so that: | ||
1802 | * "item" -> adds item to list | ||
1803 | * "-item" -> removes item from list | ||
1804 | * "+item" -> adds item to list | ||
1805 | * "=item" -> clear list, add item | ||
1806 | * | ||
1807 | * For example: | ||
1808 | * ,a,,,b,,,c, -> a,b,c | ||
1809 | * a,,b,,,c,a -> a,b,c | ||
1810 | * a,b,c,-a -> b,c | ||
1811 | * a,b,c,-a,a -> b,c,a | ||
1812 | * a,+b,c -> a,b,c | ||
1813 | * a,b,=c,d -> c,d | ||
1814 | * a,b,c,= -> | ||
1815 | */ | ||
1816 | profile_list_normalize(list); | ||
1817 | |||
1818 | /* Count items: comma count + 1 */ | ||
1819 | size_t count = 1; | ||
1820 | for (i = 0; list[i]; ++i) { | ||
1821 | if (list[i] == ',') | ||
1822 | ++count; | ||
1823 | } | ||
1824 | |||
1825 | /* Collect items in an array */ | ||
1826 | char *in[count]; | ||
1827 | count = 0; | ||
1828 | in[count++] = list; | ||
1829 | for (i = 0; list[i]; ++i) { | ||
1830 | if (list[i] != ',') | ||
1831 | continue; | ||
1832 | list[i] = 0; | ||
1833 | in[count++] = list + i + 1; | ||
1834 | } | ||
1835 | |||
1836 | /* Filter array: add, remove, reset, filter out duplicates */ | ||
1837 | for (i = 0; i < count; ++i) { | ||
1838 | char *item = in[i]; | ||
1839 | assert(item); | ||
1840 | |||
1841 | size_t k; | ||
1842 | switch (*item) { | ||
1843 | case '-': | ||
1844 | ++item; | ||
1845 | /* Do not include this item */ | ||
1846 | in[i] = 0; | ||
1847 | /* Remove if already included */ | ||
1848 | for (k = 0; k < i; ++k) { | ||
1849 | if (in[k] && !strcmp(in[k], item)) { | ||
1850 | in[k] = 0; | ||
1851 | break; | ||
1852 | } | ||
1853 | } | ||
1854 | break; | ||
1855 | case '+': | ||
1856 | /* Allow +/- symmetry */ | ||
1857 | in[i] = ++item; | ||
1858 | /* FALLTHRU */ | ||
1859 | default: | ||
1860 | /* Adding empty item is a NOP */ | ||
1861 | if (!*item) { | ||
1862 | in[i] = 0; | ||
1863 | break; | ||
1864 | } | ||
1865 | /* Include item unless it is already included */ | ||
1866 | for (k = 0; k < i; ++k) { | ||
1867 | if (in[k] && !strcmp(in[k], item)) { | ||
1868 | in[i] = 0; | ||
1869 | break; | ||
1870 | } | ||
1871 | } | ||
1872 | break; | ||
1873 | case '=': | ||
1874 | in[i] = ++item; | ||
1875 | /* Include non-empty item */ | ||
1876 | if (!*item) | ||
1877 | in[i] = 0; | ||
1878 | /* Remove all allready included items */ | ||
1879 | for (k = 0; k < i; ++k) | ||
1880 | in[k] = 0; | ||
1881 | break; | ||
1882 | } | ||
1883 | } | ||
1884 | |||
1885 | /* Copying back using in-place data works because the | ||
1886 | * original order is retained and no item gets longer | ||
1887 | * than what it used to be. | ||
1888 | */ | ||
1889 | char *pos = list; | ||
1890 | for (i = 0; i < count; ++i) { | ||
1891 | char *item = in[i]; | ||
1892 | if (!item) | ||
1893 | continue; | ||
1894 | if (pos > list) | ||
1895 | *pos++ = ','; | ||
1896 | while (*item) | ||
1897 | *pos++ = *item++; | ||
1898 | } | ||
1899 | *pos = 0; | ||
1900 | return list; | ||
1901 | } | ||
1902 | |||
1903 | void profile_list_augment(char **list, const char *items) | ||
1904 | { | ||
1905 | char *tmp = 0; | ||
1906 | if (asprintf(&tmp, "%s,%s", *list ?: "", items ?: "") < 0) | ||
1907 | errExit("asprintf"); | ||
1908 | free(*list); | ||
1909 | *list = profile_list_compress(tmp); | ||
1910 | } | ||