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

Proposed by Kyle Fazzari on 2016-05-02
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 2016-05-02 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 on 2016-05-02

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

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 on 2016-05-02

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

135. By Kyle Fazzari on 2016-05-02

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