Arch Linuxのパーティショニングをやり直した備忘録

3月くらいにArch Linuxを常用しはじめたんですが、完全に馬鹿なので、/, /var, /homeをパーティション用意していてかつすべてbtrfsにしていました。

通常Linuxをデスクトップ用途で使う場合パーティション分ける必要ないというのを知らなかった*1ので非常に厳しい感じにDockerがイメージを無駄遣いしている状態でした。

まあそういうわけでパーティショニングをやりなおすという作業をしました。環境自体はそのまま生き残っています。

そういうわけでいろいろちょっと前にTwitterで騒いでいたら老師おるみんさん@kotatsu_miからこんな感じのリプライを頂いた。

また、btrfsのプロからもこんなリプライをもらった

まあそういうわけでおるみんさんからHDDを借りてbtrfs sendを使ってグッとまとめてfstabとブートローダーだけ書き換えてなんとかしました*2

スナップショットの作成

とりあえずスナップショットを作成します。

$ btrfs subvolume snapshot -r / /root_backup
$ btrfs subvolume snapshot -r /home /home/home_backup
$ btrfs subvolume snapshot -r /var /var/var_backup

みたいな感じにします。-rをつけてるのはsendできるのはRead Onlyなスナップショットやサブボリュームだけだからですね。

Dockerが/var/lib/docker/btrfs/subvolumesにたくさんサブボリュームを作ってるんですが、色々やってたら/varの容量(10GBしかとってなかった)が無くなって破滅したので面倒になって全部消しました。

スナップショットは再帰的にとってもらえないので、そのへんをちゃんとやりたければ、

$ btrfs subvolume list (mount point) | cut -d' ' -f8 | xargs -I$ btrfs subvolume snapshot -r (mount point)$ (mount point)/$_backup

みたいな感じでスナップショットをとるか、(検証してないけど)

$ btrfs subvolume list (mount point) | cut -d' ' -f8 | xargs -I$ btrfs property set (mount point)$ ro true

とかすればサブボリュームがRead Onlyになるはずなのでおそらくbtrfs sendでおくれるはず

スナップショットを外のハードディスクに逃がす

逃します。とりあえずおるみんさんからかりたHDDをbtrfsでフォーマットしてマウントします。

$ mkfs.btrfs /dev/sdb1
$ mkdir /orumin
$ mount /dev/sdb1 /orumin

んでもってbtrfs sendします

$ btrfs send -v /root_backup | btrfs receive /orumin/

他のサブボリュームも同様にぶん投げます

パーティションを切り直してサブボリュームをリストアする

とりあえず順番にもどしていきます。このときroot_backupとかいう名前のままだとだるいのでリストア前なり後なりでサブボリュームの名称を変更しておきましょう。 切り直したパーティション/mntにマウントしておきます。この作業はArchのLive Imageでやっています。

$ btrfs send /orumin/root_backup | btrfs receive /mnt/
$ mv /mnt/root_backup /mnt/root

このまま/mnt/root/homeなどを戻していくんですが、先にスナップショットの名称を変更している場合は同一名称のディレクトリがあるとsend/receiveできないので、いろいろします。

$ btrfs property set /mnt/root ro false
$ rm -r /home
$ btrfs send /orumin/home | btrfs receive /mnt/root/
$ btrfs property set /mnt/root/home ro false

という感じでやります。/varの中身とかに既になんか入ってたらいい感じにしてください。何にしても最終的にはRead Onlyだとこまるので最後には全部Read Onlyを外します。

fstabの書き換え

一応全部移し終えてRead Only外せたらarch-chrootとかしてちゃんと動くかを確認しておきましょう。んで、fstabの書き換え。

どうせUUIDとか覚えられないので、

$ ls -l /dev/disk/by-uuid/ | vim -

とかしてバッファに一覧を表示した状態でfstabに書くUUIDを書き換えます。

このままだと/をマウントできないのでオプションでsubvol=/rootを追加しておきます。お好みでcompress=lzo

ブートローダの書き換え

ブートローダのオプションも書き換えます。

ブートローダのオプションにはroot=PARTUUID=<Partition UUID>みたいなのを書くのでさっきみたいにして

$ ls -l /dev/disk/by-partuuid | vim -

で見ながらブートローダを書き換えます。自分はSystemd-Bootを使ってるのでoptionsのパラメータを書き換えればOKでした。例によってこのときオプションにrootflags=subvol=/rootをくっつけないと起動失敗するので注意、ブートローダは生きてるので焦らずやっていきをすれば大丈夫。

おわりに

こんなことをしなくても良いようにみなさんはちゃんとArch Linux Wikiを読みましょう。

*1:ちゃんと読んでなかった

*2:UEFIなので割とかんたんにできた

内定式が近づいて来た

来年度からは紀尾井町のクソデカビルで戦うんだな、と思うと不安でいっぱいです。

学部新卒で年収をあの会社であげるのは結構難しいと思うので、そういう部分を覆せるくらいのやっていきができると最高だなと思っています。

まあそもそもそこそこの金がもらえて技術で遊ぶ余裕があって、使える技術が増やせればいいなと思っているだけなので不安もクソもとりあえず理不尽な部署とかに配属されないで欲しいくらいしかないんですが。

ブログで内定出た話は多少あったが、結局どこにするとかは書いてなかったのですが、目黒のドリ社と表参道の?社と紀尾井町のY社の内定をもらって最終的にYにすることになりました。

そこそこSNSでの発言に問題がある自覚もあるし、社会人になるにあたってその辺りをドデカ企業でシュピッとできると良さそうだなと思っていますが、御社の人間で邪悪なフォロワーがいるので不安です。

絶対に生き残って年収無限にあげてえ…

メッセージを特定個人に盗聴される恐れがある際の現実的な対策手法を考える

近況ですが、AliceとBobがメッセージをやりとりしている内容をAliceの妹Eve*1がAliceが寝ている間に端末の指紋認証を突破し盗み見てスクリーンショットを撮りAliceに直接送りつける嫌がらせをしていることが判明しました。*2 この状況のとき、各人が行える現実的なメッセージの難読化、あるいは暗号化の手法を考えたい。

私は研究をしていないと過去言われているのできっと研究をしていないのですが、配属された研究室の中には暗号理論に関わるものがいたり、私は符号理論に関わっていたりするので、そのあたりの知識を利用して考察していく。

共通鍵暗号を用いる

共通鍵暗号を用いればメッセージを比較的簡単に暗号化、あるいは復号化できる。

文字列を符号なし8ビットのバッファーに変換し、鍵文字列を用いて何らかの計算を適用しそれを再度文字列に戻すなどの方法が妥当な手法だと思われる。

しかし今回の場合は端末のほぼフルアクセスを得られるため復号化ツールもEveに利用されてしまうケースが想定できる。また、そもそもの共通鍵自体がAliceの端末から漏洩してしまう可能性が高いためあまり綺麗な手法ではない。

公開鍵暗号を用いる

公開鍵暗号を用いる場合送信メッセージの暗号化の鍵と受信メッセージの復号化の鍵の利用が想定できる。

公開鍵暗号とは言いつつもそもそも鍵自体は公開しておく必要はなく、それぞれの鍵に対応する復号鍵を計算することはほぼ不可能なので各々秘密鍵と公開鍵を所持しているだけなのでメッセージの全てがEveに復号化されるケースはなくなる。

しかしEveの目的は嫌がらせなので、この手法を用いても片側のメッセージは盗み出されてしまうためあまり効果がないという欠点が残ってしまう。

比較的単純な符号化を用いる

ハフマン符号化のように、ハフマンテーブルさえわかれば符号を復号出来るような符号化を考える。

この場合、符号は語頭符号であれば何でもよく、情報ビットたる元メッセージを符号化するルール自体は各メッセージごとに変更できるため鍵が盗まれたらメッセージが複合できるという様なパターンを避けることができる。

また、今回のケースでは送信した情報が誤って受信されるケースを想定しなくて良い為、符号化の際には符号語同士の距離*3を考慮する必要がないため、符号化のバリエーションはおそらく可算無限個程度あると想定できる。

複数の符号化を用いて難読化をすることで、正しい復号化手法をそれぞれにわからない形で伝えることができればほぼメッセージの盗聴は防げるはずである。

しかし現実的にそんな面倒なことをしていたらメッセージの伝送効率が悪すぎる為とてもじゃないが採用するのは難しそうだ。

Eveをなんとかする

これはソーシャルハックなんですが、Eveを社会的に破壊できれば問題ないというのがある。

グッと生命を絶たせたりだとか、一般社会から隔絶するとか、ブタ箱にぶち込むとか方法は様々だが、それをなんとかしてやろうと思うと割に合わないコストがかかったりするので現実的ではない。

これが実行できればかなり心の平穏が保たれるのだが、AliceがEveの親族であるので非常に面倒そうである。

人類を滅ぼす

人一人の手では不可能だが人類が滅びればメッセージの伝達そのものが不要になるので問題が消える。

第三次世界大戦…ッ!頼む!!!!!!!!!!

*1:よくある暗号理論の文脈ではそんな設定は無い

*2:悪意は無いらしいとの弁明はあったがそもそも不正アクセス禁止法に抵触します

*3:距離関数の意味で

ツイートにぶら下がってるリプライのユーザーを取得してブロックリストをエクスポートするやつを作った

これ

リポジトリ github.com

やってること

渡されたURLをNode.jsでGETしてスクレイピングしてユーザーを取得して、ガッとJSONを返すAPIをサーバ側 (https://mysticdoll.com/tools/tweet/tweetThread) で用意する

あとはReactでフロントエンドを設計。おしまい。

ファイルをダウンロードするところはObject.createObjectURLであれこれすればできる。詳しくはコード読むかなんか質問して。

任意の場所からAPI叩けたほうが良いかなと思ってついでにnginxとletsencriptをいじってmysticdoll.comにHTTPSを通しました。

こちらからは以上です。

ES6 class syntaxによって生成されたprototype上のunenumerableなメンバを列挙したかった…

class User {
  constructor(name, screenName, userId) {
    this.name = name;
    this.screenName = screenName;
    this.userId = userId;
  }
  get userPage() {
    return `https://twitter.com/${this.screenName}`;
  }
}

によって作られたUserインスタンスの配列をJSON.stringifyしてuserPageも含めてJSON化したい。

これは単一のオブジェクトに対してJSON.stringifyする場合と同値なので、それを考えると

let descriptor = Object.getOwnPropertyDescriptor(user, "userPage");
descriptor.enumerable = true;
Object.defineProperty(user, "userPage", descriptor);
JSON.stringify(user);

とすればいいかなと思うんですが、これではダメ。そもそもprototypeメンバの話なので違うのかなと思い

let descriptor = Object.getOwnPropertyDescriptor(User.prototype, "userPage");
descriptor.enumerable = true;
Object.defineProperty(User.prototype, "userPage", descriptor);
JSON.stringify(user);

としてもダメ、関係ないけど

user[Symbol.unscopables] = { userPage: false };
User.prototype[Symbol.unscopables] = { userPage: false };

でもダメ。当然JSON.stringifyで出来ないのでObject(user)してもダメ。

prototypeメンバからも列挙不可能なのでObject.keysとかでも拾えないので

  toObject() {
    return [...Object.keys(this), ...Reflect.ownKeys(this.constructor.prototype)].filter(key => key !== "constructor").reduce((obj, key) => {obj[key] = this[key]; return obj}, {});
  }

みたいな関数を生やすしかないっぽい気がしてきた。

これだったら受け側で新たにプロパティ生やしたほうが楽だなあとなり、厳しい。

一々定義時にプロパティを書かなくていいからgetter書いてたんだが、そういうわけにもいかないっぽい

Fibonacci数列

メモ化再帰とかの話読んでたらちょっと思い出したので書く。

let fib = n => n === 0 ? 0 : (n === 1 ? 1 : (n > 1 ? fib(n - 1) + fib(n - 2) : void(0)));

みたいなのを書くと、 {\displaystyle \mathcal{O} ({\alpha}^n)} ( {\displaystyle \alpha = \frac{\sqrt{5} + 1}{2}}) の計算量になるはず(ほんまか?)

これを { \displaystyle \mathcal{O} (n)}まで下げたい

まあ、こうする

let fib_seq = (n) => {
  if(n === 0) return [0];
  if(n === 1) return [1, 0];
  if(n > 1) {
    let seq = fib_seq(n - 1);
    return [seq[0] + seq[1], ...seq];
  }
};

let fib = n => fib_seq(n)[0];

fib_seqn番目までの数列を取得するやつなんですけど、やってることってn - 1番目までの配列をとってきてその添字01を足して配列に積むだけなので、たぶん {\displaystyle \mathcal{O} (n)}で済むはず。その一番上を拾うといい感じになる。

このやり方は去年大学の講義でPrologで実装するやつを見たんだけど、忘れそうだったから一応書いておいた。

まあ普通に漸化式解いて一般項求めて誤差を丸めれば  {\displaystyle \mathcal{O} (1) }だが…*1

*1:調べたら行列とか使って頑張ると  {\displaystyle \mathcal{O} (n \log n)}まで下がるらしい

単位が出ていた

単位が出ていたので卒研と余剰2単位クリアで大学全クリっぽい、幸せのあり方、心、社会への不安、無理

無理なので人間が唐突に大量に破壊されて欲しくなってきた

幸せってなんや、俺だってなあ、頭使ってなさそうな楽しそうな人間になりたかった、今からはなりたくない

東方永夜抄のスペルプラクティスでインペリシャブル・シューティングを繰り返しやっていた頃が一番幸せだった、あの時間を永遠にくれ、藤原妹紅さんの弾幕を、たのむ

後期余剰単位として何を取るか考えていない、計算機科学っぽい単位が少なすぎる、何故俺は数学系へ、数値計算の講義で降ってくるあらゆる処理をメイン関数に詰め込んだお弁当箱、よくわからないまま過ぎていった解析学、何もかもがわからない、おれは、なぜ…