20210225のLinuxに関する記事は8件です。

fs.protected_symlinks(シンボリックリンクの保護)について

最近のLinuxではシンボリックリンクに制限が加えられている。知らなかった。

シンボリックリンクとは、Windowsのショートカットのようなものである。ただし、ファイルシステムレベルで実装されているので、アプリ側は何もしなくても、シンボリックリンクを開くとリンク先のファイルが開かれる。

例えば、最近RedHat系のLinuxのパッケージ管理がyumからdnfになった。「yumと打っても動くように、/usr/bin/dnfを/usr/bin/yumをコピーしておこうかな」というときに、リンク先が/usr/bin/dnfの/usr/bin/yumというシンボリックリンクを作っておくと、ディスク容量を消費することなく目的が達成できる。

Linuxでは誰でもシンボリックリンクを作れる上に、アプリ側は何もしなくても……というか特別に対処をしないとリンク先のファイルを開いてしまうので、脆弱性になりがち。

7-1. シンボリックリンクの悪用

脆弱性を作り込まないのがとても大変。というか無理では。このIPAのページにも完璧に対処したコードは載っていないし、「であろう」で締められている。

(注3・実際にはrealpath( )ライブラリ関数の呼び出しとsafecreat( )関数の呼び出しの間にわずかな時間間隔が存在するためレースコンディションが発生する。さらにrealpath( )ライブラリ関数自体の実装でもlstat( )を繰り返し行い,シンボリックリンクかどうか判断しているので,やはりレースコンディションが発生する。レースコンディションを排除する完璧な実装は困難である。妥当な設計としては,ファイルパスを構成するすべてのディレクトリのパーミッションをチェックし,スーパユーザまたはアプリケーションの実行ユーザのみに書き込み権限があることを確認し,さらにシンボリックリンクでないことを確認する,という手法であろう。)

ということで(?)Linuxに緩和策が追加されていた。

[root@tk2-239-29470 ~]# docker run --rm -it centos:8
[root@a327c9f3009e /]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="8"
 :
[root@a327c9f3009e /]# adduser user
[root@a327c9f3009e /]# su user
[user@a327c9f3009e /]$ cd /tmp/
[user@a327c9f3009e tmp]$ echo "hello" > target
[user@a327c9f3009e tmp]$ ln -s target symbolic_link
[user@a327c9f3009e tmp]$ ls -al
total 32
drwxrwxrwt 1 root root 4096 Feb 25 13:47 .
 :
lrwxrwxrwx 1 user user    6 Feb 25 13:47 symbolic_link -> target
-rw-rw-r-- 1 user user    6 Feb 25 13:47 target

適当にユーザーを作り、リンク先が/tmp/targetの/tmp/symbolic_linkというシンボリックリンクを作成。

[user@a327c9f3009e tmp]$ cat symbolic_link
hello
[user@a327c9f3009e tmp]$ echo "world" >> symbolic_link
[user@a327c9f3009e tmp]$ cat symbolic_link
hello
world
[user@a327c9f3009e tmp]$ cat target
hello
world

symbolic_linkを読むとtargetの内容が読み出されるし、symbolic_linkに書き込むとtargetに書き込まれる。これがシンボリックリンクである。

ここで、rootに戻ってsymbolic_linkを読み書きしようとしてみると……、

[user@a327c9f3009e tmp]$ exit
exit
[root@a327c9f3009e /]# cd /tmp/
[root@a327c9f3009e tmp]# cat symbolic_link
cat: symbolic_link: Permission denied
[root@a327c9f3009e tmp]# echo "aaaa" >> symbolic_link
bash: symbolic_link: Permission denied

失敗する。これが緩和策。rootでもPermission deniedになることがあるんだ。詳細はここに書かれている。

https://www.kernel.org/doc/Documentation/sysctl/fs.txt#:~:text=symlinks%20are%20permitted%20to%20be%20followed

protected_symlinks:
:
When set to "1" symlinks are permitted to be followed only when outside a sticky world-writable directory, or when the uid of the symlink and follower match, or when the directory owner matches the symlink's owner.

  • Stickyでworld-writableなディレクトリにあるシンボリックを辿るのは禁止される
    • でも、シンボリックリンクを作ったユーザーならOK
    • ディレクトリの所有者が作ったシンボリックリンクもOK

と読んだほうが分かりやすいか。

Stickyというのはsticky bitのことで、これがディレクトリについていると、書き込みが可能なディレクトリでも、その中のファイルの削除や名前の変更はファイルの所有者しかできなくなる(普通はファイルの所有者でなくてもディレクトリの書き込み権限を持っていれば削除できる)。これとシンボリックリンクの制限を直接紐付ける理由は分からないので、stickyでworld-writableな/tmpや/var/tmpを対象にしたいということなのだと思う。最後も/tmpの所有者はrootなので、rootが作ったシンボリックリンクはOKということにしたいのだと思う。

一時的に無効にしたければ、

sysctl fs.protected_symlinks=0

恒久的に無効にしたければ、どこかに設定ファイルがあるはずで、それを書き換える。CentOS 8ならば、

/usr/lib/sysctl.d/50-default.conf
 :
# To override settings in this file, create a local file in /etc
# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments
# there.
 :
# Enable hard and soft link protection
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

注意書きにあるように、90-override.confを書き換えれば良いのかな。

↑ではDockerで試していた。Dockerはホストからカーネルパラメタを持ってきていて、起動時の--sysctlによる上書きも(まだ)できない。

# docker run --rm -it --sysctl fs.protected_symlinks=0 centos:8
invalid argument "fs.protected_symlinks=0" for "--sysctl" flag: sysctl 'fs.protected_symlinks=0' is not whitelisted
See 'docker run --help'.

ホスト側で設定を変えるしかなさそう。

しかし……シンボリックを悪用した攻撃を考えてみても、/tmpに作っているシンボリックを他のディレクトリに作るだけなような。/tmpの中にstickyではないディレクトリを作るだけで良い。どういう攻撃が防げるのだろう :thinking:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IPコマンド

はじめに

忘れないためにここで書く。

コマンドの基本の使い方

ip addr [ COMMAND ] ADDRESS dev IFNAME

dev: device

IPアドレスの確認

# ip addr show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

特定のインタフェースに絞る

# ip addr show dev eth0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

IPバージョン指定

ip -4 addr show dev eth0 
ip -6 addr show dev eth0

※addrをaだけにしてもOK!
例、ip -4 a dev eth0

IPアドレスの追加/削除

ip addr <COMMAND> ADDRESS dev IFNAME

追加

ip addr add 192.168.10.10/24 dev eth0

削除

ip addr del 192.168.10.10/24 dev eth0

ネットワークインターフェースの情報確認

# ip link show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff

※IPアドレス表示されない点が「ip addr show」と違う点です。

特定のインタフェースに絞る

# ip link show eth0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff

インタフェースの接続・切断

ip link set dev {DEVICE} {up|down}

ネットワークインターフェースUp

ip link set eth0 up

ネットワークインターフェース切断

ip link set eth0 down



参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IPコマンドの基本の使い方

ip [OPTION] OBJECT {COMMAND | help}

よく使うOPTIONは、
1. -4 – IPV4表示
2. -6 - IPV6表示

よく使うOBJECTは、
1. link (l) – ネットワークインターフェースを表示する時に使う
2. address (addr/a) – IPアドレスの表示・変更の時に使う
3. route (r) – Routingの表示・設定するときに使う

ip helpを叩くと詳細が表示される。

IPアドレスの確認

よく使うコマンド

  • show
  • add
  • del
# ip addr show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

特定のインタフェースに絞る

# ip addr show dev ens3

2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 02:42:ac:11:00:10 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.16/16 brd 172.17.255.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:10/64 scope link 
       valid_lft forever preferred_lft forever

dev = device

結果の読み方

mtu 1500

maximum transmission unit = 1500 bytes
ネットワーク上で送信可能なパケットの最大サイズは1500バイト

link/ether

macアドレス

inet

IPv4 アドレス
brd: ブロードキャストアドレス
scope global: 送信先はグローバル
lft: (Lifetime)有効期限

inet6

IPv6 のアドレス
scope link: 送信先はローカルネットワーク内のみ

Scope補足

Scope Description
global valid everywhere
site valid only within this site (IPv6)
link valid only on this device
host valid only inside this host (machine)

IPバージョン指定

ip -4 addr show dev eth0 
ip -6 addr show dev eth0

※addrをaだけにしてもOK!
例、ip -4 a dev eth0

IPアドレスの追加/削除

追加

ip addr add 192.168.10.10/24 dev eth0

削除

ip addr del 192.168.10.10/24 dev eth0

ネットワークインターフェースの情報確認

# ip link show

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff

※IPアドレス表示されない点が「ip addr show」と違う点です。

特定のインタフェースに絞る

# ip link show eth0
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff

インタフェースの接続・切断

ip link set dev {DEVICE} {up|down}

ネットワークインターフェースUp

ip link set eth0 up

ネットワークインターフェース切断

ip link set eth0 down


Routing

Youtube Video

subnetging

Youtube Video



- 参考1
- 参考2
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Big Surにアップデートしたらvagrantが起動しなくなった件

Big Surにアップデートしたところ、vagrantが起動しなくなった。

↓エラー

There was an error while executing VBoxManage, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["startvm", "b43f8d3f-5d11-4ab4-8ba2-d8896c0c0492", "--type", "headless"]

Stderr: VBoxManage: error: The virtual machine 'ubuntu64_18_default_1592808456466_80230' has terminated unexpectedly during startup with exit code 1 (0x1)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component MachineWrap, interface IMachin

とのこと。
調べた感じでは、virtualboxとvagrantをアップデートすれば良さそうだが...

ひとまず、vagrantをアップデートしてみる。
よくわからなかったので、mac osの2.2.14をダウンロード。

vagrant --version
⇨Vagrant 2.2.14

バージョンアップできている。
続いてvirtualboxをダウンロード。
公式サイトからvirtualbox 6.1.18をmacosでインストールした。

しかし...エラーの内容が全く変わらない。
だが、他の方の記事を確認し、ダウンロードしたアプリケーションを許可を設定から実行して再起動を行った結果、無事起動し、ssh接続も行えた。

以下参考にしたwebサイト
https://qiita.com/syota_19910612bscplog/items/ee7e06cd23603fa529dd
↑非常にわかりやすい他の方の記事

https://www.virtualbox.org/wiki/Downloads
↑virtualbox公式サイトのダウンロード画面

https://www.vagrantup.com/downloads
↑vagrant公式サイトのダウンロード画面

ほとんど無益な記事ですみません。初投稿なので許してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FrontISTRをIntel oneAPIを使って構築する

※自分用のメモとして書きました。

FrontISTRをWSL2上のUbuntu 20.04へインストールする。恐らく、Ubuntu 18.04や16.04でもインストール出来ると思います(確認はしていない)。

Intel oneAPI

cd /tmp
wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB
rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB

sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main"
sudo apt update
sudo apt install intel-hpckit intel-basekit

cmake

cmake-3.19.2以上が必須。それ以下のバージョンだとMPIライブラリが認識出来なかった。

wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main'
sudo apt-get update
sudo apt install cmake
sudo apt install pkg-config

最後の pkg-config は無くても問題無いが、Warning抑止のため入れておく。

これをやっておけば、定期的に

sudo apt update
sudo apt dist-upgrade

しておけば最新版がインストールされる。

FrontISTR

自分用に書いたビルドスクリプトをダウンロードし、実行すると MPI, OpenMP, MUMPS, Metis, Trilinos ML, LAPACK, MKL, REVOCAP_Refinerを有効にした FrontISTR が $HOME/local/binfistr1 hec2rcap hecmw_part1 hecmw_vis1 rconv rmerge としてインストールされる。

git clone git@github.com:michioga/fistr_build_script
cd fistr_build_script
./fistr_build.sh

fistr_build.sh は単なるシェルスクリプトなので、必要に応じて編集する。

インストールされた fistr1 へリンクされているライブラリを確認する。

ldd fistr1
        linux-vdso.so.1 (0x00007ffdf4399000)
        libmkl_intel_lp64.so.1 => /opt/intel/oneapi/mkl/latest/lib/intel64/libmkl_intel_lp64.so.1 (0x00007f792b662000)
        libmkl_intel_thread.so.1 => /opt/intel/oneapi/mkl/latest/lib/intel64/libmkl_intel_thread.so.1 (0x00007f7927d69000)
        libmkl_core.so.1 => /opt/intel/oneapi/mkl/latest/lib/intel64/libmkl_core.so.1 (0x00007f791fda3000)
        libiomp5.so => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libiomp5.so (0x00007f791f99a000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f791f96e000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f791f81f000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f791f819000)
        libmpifort.so.12 => /opt/intel/oneapi/mpi/2021.1.1//lib/libmpifort.so.12 (0x00007f791f45b000)
        libmpi.so.12 => /opt/intel/oneapi/mpi/2021.1.1//lib/release/libmpi.so.12 (0x00007f791e0e2000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f791e0d5000)
        libmpicxx.so.12 => /opt/intel/oneapi/mpi/2021.1.1//lib/libmpicxx.so.12 (0x00007f791deb5000)
        libifport.so.5 => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libifport.so.5 (0x00007f791dc87000)
        libifcoremt.so.5 => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libifcoremt.so.5 (0x00007f791dae7000)
        libimf.so => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libimf.so (0x00007f791d45f000)
        libsvml.so => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libsvml.so (0x00007f791b8e6000)
        libirc.so => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libirc.so (0x00007f791b66e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f791b47c000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f791b461000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f791b280000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f792c39f000)
        libfabric.so.1 => /opt/intel/oneapi/mpi/2021.1.1//libfabric/lib/libfabric.so.1 (0x00007f791b03a000)
        libintlc.so.5 => /opt/intel/oneapi/compiler/2021.1.2/linux/compiler/lib/intel64_lin/libintlc.so.5 (0x00007f791adc2000)

これで gfortran, OpenMPI 無しでも、お金を掛けずに FrontISTR がコンパイル出来る様になった。

./fistr1  -h
##################################################################
#                         FrontISTR                              #
##################################################################
---
version:    5.1.1
git_hash:   b2fc72cd8580639457fb323862bf7c49680003ca
build:
  date:     2021-02-25T14:10:59+0900
  MPI:      enabled
  OpenMP:   enabled
  option:   "-p --with-tools --with-metis --with-mumps --with-lapack --with-ml --with-parmetis --with-mkl "
  HECMW_METIS_VER: 5
usage: [ mpirun -np <mpiprocs> ] fistr1 [options]
 -h: Show this help message.
 -v: Show version.
 -t <n>: Set number of OpenMP threads
 -c <Path of control file>: Use this control file. Default ./hecmw_ctrl.dat
--debug: Show debug messages.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

基本的な環境変数の設定

システムを利用する全ユーザがログイン後参照するファイル

/etc/profile
ログイン時に全ユーザが参照する


~/.bash_profile ~/.profile

各ユーザが利用するファイル

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CentOS 8によるループバックデバイスを使ったLVM作成

環境

OS:CentOS Linux release 8.3.2011

作業内容

OpenStackのPackstackによる自動構築について検証する。PackstackではCinderによる外部ストレージを設定するが、本環境ではサーバー1台のオールインワン構成で検証しているため外部ストレージは存在しない。

そこで、Linuxのループバックデバイスを使ってボリュームを作成し検証を行う。
本記事ではCentOS 8.3におけるループバックデバイスの作成およびLVMボリュームの作成方法を記載する。

ループバックデバイスとは

ファイルをファイルシステムのようにマウントできる機能のことである。

手順

現在のループバックデバイスの状況を確認する。

# losetup -a

何も表示されない場合は/dev/loop0が利用可能なので、任意のファイルをループバックデバイス/dev/loop0に割り当てる。

# losetup /dev/loop0 /root/<File name>

ループバックデバイスにLVMパーティションを作成する。(以下はGPTで割り当てる場合)

# parted -s /dev/loop0 'mklabel gpt'
# parted -s /dev/loop0 'mkpart primary 0 -1'
Warning: The resulting partition is not property aligned for best performance.
# parted -s /dev/loop0 'set 1 lvm on'
# parted -s /dev/loop0 'print'

ループバックデバイス/dev/loop0にLVMボリュームを作成する。今回はvgcreateコマンドでボリュームグループを作成する際に、VG名に「cinder-volumes」を指定する。

# partprobe /dev/loop0
# cat /proc/partitions
(省略)

# pvcreate -y -ff /dev/loop0p1
 Physical volume "/dev/loop0p1" successfully created
# vgcreate -y -f cinder-volumes /dev/loop0p1
 Volume group "cinder-volumes" successfully created

以上

補足

今回はCinderボリュームをループバックデバイスで用意しましたが、本番環境ではNovaが稼働するコンピュートノードに接続されたiSCSIやFC接続の外部ストレージを使用するのが一般的です。そのため本番環境ではループバックデバイスではなく、外部ストレージが提供するブロックデバイスに、CinderボリュームのLVMを作成する必要があります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

xubuntu に software Center をインストール

まだまだ寒い日が続きますが、皆さんお元気ですか?
今日は愛用している xubuntu を使いやすくするため
ソフトウェアセンターをインストールします。
ブラウザーが Firefox 1本では使いにくいので
Vivaldi か Opera を入れたいのですが
面倒なコマンドを使わないとインストールできない・・・
そこで
Gnome softwere Center を入れてしまいます。
sudo apt install gnome-software これだけです。
スクリーンショット_2021-02-25_03-00-13-
ご覧のように・・いとも簡単に入ります。
さて! Vivaldi をインストールします。
Vivaldi 本家から deb パッケージをダウンロード
ダウンロードしたファイルを
「ソフトウェアのインストーラーで開く」を選択。
簡単に入ります。
スクリーンショット_2021-02-25_04-04-29-
ついでに言うと Opera も簡単に入ります。
考えてみれば xubuntu は ubuntu の親戚。
ubuntu でデフォルト仕様の gnome-software が使えて当たり前かも?
何だ・・・ややこしいコマンドなんて要らなかったですよ(笑)
では、また・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む