aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/profile.c140
2 files changed, 143 insertions, 0 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
452void profile_add(char *str); 452void profile_add(char *str);
453void profile_add_ignore(const char *str); 453void profile_add_ignore(const char *str);
454char *profile_list_normalize(char *list);
455char *profile_list_compress(char *list);
456void profile_list_augment(char **list, const char *items);
454 457
455// list.c 458// list.c
456void list(void); 459void list(void);
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 9339228f4..7b5fbfedf 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -1773,3 +1773,143 @@ void profile_read(const char *fname) {
1773 } 1773 }
1774 fclose(fp); 1774 fclose(fp);
1775} 1775}
1776
1777char *profile_list_normalize(char *list)
1778{
1779 /* Remove redundant commas.
1780 *
1781 * As result is always shorter than original,
1782 * in-place copying can be used.
1783 */
1784 size_t i = 0;
1785 size_t j = 0;
1786 int c;
1787 while (list[i] == ',')
1788 ++i;
1789 while ((c = list[i++])) {
1790 if (c == ',') {
1791 while (list[i] == ',')
1792 ++i;
1793 if (list[i] == 0)
1794 break;
1795 }
1796 list[j++] = c;
1797 }
1798 list[j] = 0;
1799 return list;
1800}
1801
1802char *profile_list_compress(char *list)
1803{
1804 size_t i;
1805
1806 /* Comma separated list is processed so that:
1807 * "item" -> adds item to list
1808 * "-item" -> removes item from list
1809 * "+item" -> adds item to list
1810 * "=item" -> clear list, add item
1811 *
1812 * For example:
1813 * ,a,,,b,,,c, -> a,b,c
1814 * a,,b,,,c,a -> a,b,c
1815 * a,b,c,-a -> b,c
1816 * a,b,c,-a,a -> b,c,a
1817 * a,+b,c -> a,b,c
1818 * a,b,=c,d -> c,d
1819 * a,b,c,= ->
1820 */
1821 profile_list_normalize(list);
1822
1823 /* Count items: comma count + 1 */
1824 size_t count = 1;
1825 for (i = 0; list[i]; ++i) {
1826 if (list[i] == ',')
1827 ++count;
1828 }
1829
1830 /* Collect items in an array */
1831 char *in[count];
1832 count = 0;
1833 in[count++] = list;
1834 for (i = 0; list[i]; ++i) {
1835 if (list[i] != ',')
1836 continue;
1837 list[i] = 0;
1838 in[count++] = list + i + 1;
1839 }
1840
1841 /* Filter array: add, remove, reset, filter out duplicates */
1842 for (i = 0; i < count; ++i) {
1843 char *item = in[i];
1844 assert(item);
1845
1846 size_t k;
1847 switch (*item) {
1848 case '-':
1849 ++item;
1850 /* Do not include this item */
1851 in[i] = 0;
1852 /* Remove if already included */
1853 for (k = 0; k < i; ++k) {
1854 if (in[k] && !strcmp(in[k], item)) {
1855 in[k] = 0;
1856 break;
1857 }
1858 }
1859 break;
1860 case '+':
1861 /* Allow +/- symmetry */
1862 in[i] = ++item;
1863 /* FALLTHRU */
1864 default:
1865 /* Adding empty item is a NOP */
1866 if (!*item) {
1867 in[i] = 0;
1868 break;
1869 }
1870 /* Include item unless it is already included */
1871 for (k = 0; k < i; ++k) {
1872 if (in[k] && !strcmp(in[k], item)) {
1873 in[i] = 0;
1874 break;
1875 }
1876 }
1877 break;
1878 case '=':
1879 in[i] = ++item;
1880 /* Include non-empty item */
1881 if (!*item)
1882 in[i] = 0;
1883 /* Remove all allready included items */
1884 for (k = 0; k < i; ++k)
1885 in[k] = 0;
1886 break;
1887 }
1888 }
1889
1890 /* Copying back using in-place data works because the
1891 * original order is retained and no item gets longer
1892 * than what it used to be.
1893 */
1894 char *pos = list;
1895 for (i = 0; i < count; ++i) {
1896 char *item = in[i];
1897 if (!item)
1898 continue;
1899 if (pos > list)
1900 *pos++ = ',';
1901 while (*item)
1902 *pos++ = *item++;
1903 }
1904 *pos = 0;
1905 return list;
1906}
1907
1908void profile_list_augment(char **list, const char *items)
1909{
1910 char *tmp = 0;
1911 if (asprintf(&tmp, "%s,%s", *list ?: "", items ?: "") < 0)
1912 errExit("asprintf");
1913 free(*list);
1914 *list = profile_list_compress(tmp);
1915}