Merge lp:~kyrofa/snap-confine/create_user_common_data into lp:~snappy-dev/snap-confine/trunk

Proposed by Kyle Fazzari
Status: Needs review
Proposed branch: lp:~kyrofa/snap-confine/create_user_common_data
Merge into: lp:~snappy-dev/snap-confine/trunk
Diff against target: 292 lines (+140/-46)
2 files modified
src/main.c (+41/-6)
tests/test_create_user_data (+99/-40)
To merge this branch: bzr merge lp:~kyrofa/snap-confine/create_user_common_data
Reviewer Review Type Date Requested Status
Snappy Developers Pending
Review via email: mp+293555@code.launchpad.net

Commit message

Create user-specific common snap data directory.

Description of the change

The newest version of Snappy now supports a unversioned ("common") snap data directory for both system-wide and user-specific data. Since the launcher currently creates the other user-specific data, it makes sense to include the user-specific common data as well.

There's a caveat, though. While Snappy supports common data directories, they're as-yet unnamed (i.e. they're not represented by environment variables). They do, however, have a specific path relative to SNAP_DATA and SNAP_USER_DATA, so this PR utilizes that. The launcher will need to be updated again once a name is chosen for these paths.

To post a comment you must log in.
136. By Kyle Fazzari

Should use calloc instead of malloc to zero-init string.

Revision history for this message
Kyle Fazzari (kyrofa) wrote :

Note the lack of profile changes here. This change seems to be covered under the current profile.

Unmerged revisions

136. By Kyle Fazzari

Should use calloc instead of malloc to zero-init string.

135. By Kyle Fazzari

Create user-specific common snap data directory.

The newest version of Snappy now supports a unversioned ("common") snap data
directory for both system-wide and user-specific data. Since the launcher
currently creates the other user-specific data, it makes sense to include
the user-specific common data as well.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/main.c'
2--- src/main.c 2016-04-29 16:58:48 +0000
3+++ src/main.c 2016-05-02 17:43:18 +0000
4@@ -404,7 +404,7 @@
5 // we'll make a copy of it.
6 char *path_copy = strdup(path);
7 if (path_copy == NULL) {
8- die("failed to create user data directory");
9+ die("failed to copy path when creating directory %s", path);
10 }
11 // Open flags to use while we walk the user data path:
12 // - Don't follow symlinks
13@@ -421,7 +421,7 @@
14 fd = open("/", open_flags);
15 if (fd < 0) {
16 free(path_copy);
17- die("failed to create user data directory");
18+ die("failed to open '/' when creating directory %s", path);
19 }
20 }
21 // strtok_r needs a pointer to keep track of where it is in the string.
22@@ -435,7 +435,7 @@
23 if (mkdirat(fd, path_segment, 0755) < 0 && errno != EEXIST) {
24 close(fd); // we die regardless of return code
25 free(path_copy);
26- die("failed to create user data directory");
27+ die("failed to create directory %s", path_segment);
28 }
29 // Open the parent directory we just made (and close the
30 // previous one) so we can continue down the path.
31@@ -443,11 +443,11 @@
32 fd = openat(fd, path_segment, open_flags);
33 if (close(previous_fd) != 0) {
34 free(path_copy);
35- die("could not close path segment");
36+ die("failed to close previous path segment");
37 }
38 if (fd < 0) {
39 free(path_copy);
40- die("failed to create user data directory");
41+ die("failed to open %s", path_segment);
42 }
43 // Obtain the next path segment.
44 path_segment = strtok_r(NULL, "/", &path_walker);
45@@ -456,7 +456,7 @@
46 // Close the descriptor for the final directory in the path.
47 if (close(fd) != 0) {
48 free(path_copy);
49- die("could not close final directory");
50+ die("failed to close final path segment");
51 }
52
53 free(path_copy);
54@@ -476,6 +476,38 @@
55 mkpath(user_data);
56 }
57
58+void setup_user_common_data()
59+{
60+ // The common data directory is common across all versions of the
61+ // snap. Note that it doesn't have its own variable yet, so it
62+ // needs to be relative to SNAP_USER_DATA. FIXME when it has one.
63+ const char *user_data = getenv("SNAP_USER_DATA");
64+
65+ if (user_data == NULL)
66+ return;
67+ // Only support absolute paths.
68+ if (user_data[0] != '/') {
69+ die("user common data directory must be an absolute path");
70+ }
71+
72+ const char *common_folder_path = "/../common";
73+ const size_t user_data_length = strlen(user_data);
74+ const size_t common_folder_path_length = strlen(common_folder_path);
75+
76+ // +1 for NULL
77+ const size_t common_user_length = user_data_length + common_folder_path_length + 1;
78+ char *common_user_data = calloc(common_user_length, 1);
79+ if (common_user_data == NULL) {
80+ die("failed to create user common data directory");
81+ }
82+
83+ strncpy(common_user_data, user_data, user_data_length);
84+ strncat(common_user_data, common_folder_path, common_folder_path_length);
85+ common_user_data[common_user_length-1] = '\0';
86+ mkpath(common_user_data);
87+ free(common_user_data);
88+}
89+
90 int main(int argc, char **argv)
91 {
92 const int NR_ARGS = 3;
93@@ -543,6 +575,9 @@
94 // Ensure that the user data path exists.
95 setup_user_data();
96
97+ // Ensure that the user data path common across versions exists.
98+ setup_user_common_data();
99+
100 // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement
101
102 int rc = 0;
103
104=== modified file 'tests/test_create_user_data'
105--- tests/test_create_user_data 2016-04-15 20:20:28 +0000
106+++ tests/test_create_user_data 2016-05-02 17:43:18 +0000
107@@ -1,7 +1,5 @@
108 #!/bin/sh
109
110-set -e
111-
112 . $(pwd)/common.sh
113
114 cat >$TMP/unrestricted <<EOF
115@@ -43,24 +41,18 @@
116 pass=false
117 if $L snap.name.app $2 /bin/true 2>/dev/null; then
118 if $3; then
119- if [ ! -d "$1" ]; then
120- pass=false
121+ if [ -d "$1" ]; then
122+ pass=true
123 fi
124-
125- pass=true
126- else
127- pass=false
128 fi
129 else
130- if $3; then
131- pass=false
132- else
133+ if ! $3; then
134 pass=true
135 fi
136 fi
137
138 if [ -d "$1" ]; then
139- rmdir $1
140+ rmdir -p $1 --ignore-fail-on-non-empty
141 fi
142
143 if $pass; then
144@@ -70,53 +62,120 @@
145 fi
146 }
147
148+# Check user data directory creation.
149+#
150 # $1 = $SNAP_USER_DATA definition
151 # $2 = Profile name
152-# $3 = True if success is expected, false otherwise
153-run_current() {
154+# $3 = Whether or not success is expected
155+check_user_data() {
156 export SNAP_USER_DATA=$1
157 run_launcher $1 $2 $3
158 pass=$?
159 unset SNAP_USER_DATA
160
161- return $pass
162+ if [ $pass -eq 0 ]; then
163+ PASS
164+ else
165+ FAIL
166+ fi
167+}
168+
169+# Check user common data directory creation.
170+#
171+# $1 = $SNAP_USER_DATA definition
172+# $2 = Profile name
173+# $3 = Whether or not success is expected
174+check_user_common_data() {
175+ export SNAP_USER_DATA=$1
176+
177+ # There's no variable representing this right now, so we specify
178+ # relative to $SNAP_USER_DATA. FIXME when this is no longer the
179+ # case.
180+ run_launcher "$SNAP_USER_DATA/../common" $2 $3
181+ pass=$?
182+ if [ -d "$SNAP_USER_DATA" ]; then
183+ rmdir -p $SNAP_USER_DATA --ignore-fail-on-non-empty
184+ fi
185+ unset SNAP_USER_DATA
186+
187+ if [ $pass -eq 0 ]; then
188+ PASS
189+ else
190+ FAIL
191+ fi
192 }
193
194 printf "Test that an unrestricted launcher creates user data"
195-run_current $TMP/user_data unrestricted true
196+check_user_data $TMP/user_data unrestricted true
197+
198+printf "Test that an unrestricted launcher creates user common data"
199+check_user_common_data $TMP/user_data unrestricted true
200+
201
202 printf "Test that a restricted launcher creates user data"
203-run_current $TMP/user_data restricted true
204+check_user_data $TMP/user_data restricted true
205+
206+printf "Test that a restricted launcher creates user common data"
207+check_user_common_data $TMP/user_data restricted true
208+
209
210 printf "Test that an unrestricted launcher creates user data with parent directory"
211-run_current $TMP/parent/user_data unrestricted true
212+check_user_data $TMP/parent/user_data unrestricted true
213+
214+printf "Test that an unrestricted launcher creates user common data with parent directory"
215+check_user_common_data $TMP/parent/user_data unrestricted true
216+
217
218 printf "Test that a restricted launcher creates user data with parent directory"
219-run_current $TMP/parent/user_data restricted true
220+check_user_data $TMP/parent/user_data restricted true
221+
222+printf "Test that a restricted launcher creates user common data with parent directory"
223+check_user_common_data $TMP/parent/user_data restricted true
224+
225
226 printf "Test that user data can contain multiple path separators"
227-run_current $TMP//user_data unrestricted true
228+check_user_data $TMP//user_data unrestricted true
229+
230+printf "Test that user common data can contain multiple path separators"
231+check_user_common_data $TMP//user_data unrestricted true
232+
233
234 printf "Test that user data must be absolute"
235-run_current "../foo" unrestricted false
236+check_user_data "../foo" unrestricted false
237+
238+printf "Test that user common data must be absolute"
239+check_user_common_data "../foo" unrestricted false
240+
241+
242+with_symlink() {
243+ mkdir $TMP/nefarious_parent
244+ ln -s $TMP/nefarious_parent $TMP/parent
245+ $@
246+ rm $TMP/parent
247+ rmdir $TMP/nefarious_parent
248+}
249
250 printf "Testing that user data cannot be contained within a symlink"
251-mkdir $TMP/nefarious_parent
252-ln -s $TMP/nefarious_parent $TMP/parent
253-run_current $TMP/parent/user_data unrestricted, false
254-
255-printf "Test that an unrestricted launcher works when user data exists (current)"
256-mkdir $TMP/user_data
257-if run_current $TMP/user_data unrestricted true; then
258- PASS
259-else
260- FAIL
261-fi
262-
263-printf "Test that an restricted launcher works when user data exists (current)"
264-mkdir $TMP/user_data
265-if run_current $TMP/user_data restricted true; then
266- PASS
267-else
268- FAIL
269-fi
270+with_symlink check_user_data $TMP/parent/user_data unrestricted, false
271+
272+printf "Testing that user common data cannot be contained within a symlink"
273+with_symlink check_user_common_data $TMP/parent/user_data unrestricted, false
274+
275+
276+with_existing() {
277+ mkdir $TMP/user_data
278+ $@
279+}
280+
281+printf "Test that an unrestricted launcher works when user data exists"
282+with_existing check_user_data $TMP/user_data unrestricted true
283+
284+printf "Test that an unrestricted launcher works when user common data exists"
285+with_existing check_user_common_data $TMP/user_data unrestricted true
286+
287+
288+printf "Test that a restricted launcher works when user data exists"
289+with_existing check_user_data $TMP/user_data restricted true
290+
291+printf "Test that a restricted launcher works with user common data exists"
292+with_existing check_user_common_data $TMP/user_data restricted true

Subscribers

People subscribed via source and target branches